Gemaakt door de Music Masters:
Mark "Markolie20" Olieman
Daan "Daan Eising" Eising
Jesse "zdfgdfsg" van der Westen
import os
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import glob
import warnings
import plotly.express as px
from pydub import AudioSegment
import IPython.display as ipd
from IPython.display import display
from IPython.display import Audio
import librosa as lr
from librosa import load as lr_load
from librosa import amplitude_to_db
from librosa.feature import melspectrogram, mfcc, chroma_stft, spectral_flatness, zero_crossing_rate, tempogram
from librosa.beat import tempo, beat_track
from librosa.feature import spectral_contrast as lf_spectral_contrast
from librosa.feature import spectral_rolloff as lf_spectral_rolloff
from librosa import pyin, amplitude_to_db
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score
from sklearn.cluster import KMeans, AgglomerativeClustering, DBSCAN, Birch, MeanShift
from sklearn.decomposition import PCA
from sklearn.decomposition import NMF
from sklearn.preprocessing import StandardScaler, MinMaxScaler
from scipy.io import wavfile
from scipy.spatial.distance import euclidean, cityblock
class AudioFeatureExtractor:
"""
A class for extracting various audio features from an audio signal.
Attributes:
None
Methods:
mfccs(data, sfreq):
Extracts Mel-Frequency Cepstral Coefficients (MFCCs) from the audio signal.
calculate_spectrograms(audio_clips, n_fft=2048, hop_length=512, win_length=None):
Calculates spectrograms from a list of audio clips.
calculate_spectral_features(spectrograms):
Calculates spectral features (bandwidth and centroid) from a list of spectrograms.
calculate_spectral_contrast(data, sr, n_fft=2048, hop_length=512):
Calculates spectral contrast from the audio signal.
calculate_tonnetz(data, sr):
Calculates tonnetz features from the audio signal.
calculate_spectral_rolloff(data, sr, roll_percent=0.85, n_fft=2048, hop_length=512):
Calculates spectral rolloff from the audio signal.
calculate_chroma_features(data, sr, n_fft=2048, hop_length=512):
Calculates chroma features from the audio signal.
calculate_mel_spectral_contrast(data, sr, n_fft=2048, hop_length=512):
Calculates mel spectrogram and its contrast from the audio signal.
calculate_spectral_flatness(data, sr, n_fft=2048, hop_length=512):
Calculates spectral flatness from the audio signal.
zero_crossing_rate_features(data, n_fft=2048, hop_length=512):
Calculates zero-crossing rate from the audio signal.
rms_energy_features(data):
Calculates root mean square (RMS) energy from the audio signal.
"""
def __init__(self):
pass
def mfccs(self, data, sr):
"""
Extracts Mel-Frequency Cepstral Coefficients (MFCCs) from the audio signal.
Parameters:
data (numpy.ndarray): The audio signal.
sr (int): The sampling rate of the audio signal.
Returns:
dict: A dictionary containing the mean of each MFCC coefficient.
"""
mfcc_result = mfcc(y=data, sr=sr)
datadict = {}
for var in range(len(mfcc_result)):
datadict[f'mfcc{var + 1}_mean'] = np.mean(mfcc_result[var, :])
return datadict
def calculate_spectrograms(self, audio_clips, n_fft=2048, hop_length=512, win_length=None):
"""
Calculates spectrograms from a list of audio clips.
Parameters:
audio_clips (list): List of audio clips.
n_fft (int): The number of points for each FFT.
hop_length (int): The number of samples between successive frames.
win_length (int): The length of the windowing segments.
Returns:
tuple: Two lists - spectrograms and their corresponding dB-scaled versions.
"""
spectrograms = []
spectrograms_db = []
for clip in audio_clips:
stft_matrix = lr.stft(y=clip, n_fft=n_fft, hop_length=hop_length, win_length=win_length)
spectrogram = np.abs(stft_matrix)
spec_db = amplitude_to_db(S=spectrogram, ref=np.max)
spectrograms.append(spectrogram)
spectrograms_db.append(spec_db)
return spectrograms, spectrograms_db
def calculate_spectral_features(self, spectrograms):
"""
Calculates spectral features (bandwidth and centroid) from a list of spectrograms.
Parameters:
spectrograms (list): List of spectrograms.
Returns:
tuple: Two lists - spectral bandwidths and centroids.
"""
bandwidths = []
centroids = []
for spectrogram in spectrograms:
spec_bw = lr.feature.spectral_bandwidth(S=spectrogram)
spec_cn = lr.feature.spectral_centroid(S=spectrogram)
bandwidths.append(spec_bw)
centroids.append(spec_cn)
return bandwidths, centroids
def calculate_spectral_contrast(self, data, sr, n_fft=2048, hop_length=512):
"""
Calculates spectral contrast from the audio signal.
Parameters:
data (numpy.ndarray): The audio signal.
sr (int): The sampling rate of the audio signal.
n_fft (int): The number of points for each FFT.
hop_length (int): The number of samples between successive frames.
Returns:
numpy.ndarray: Spectral contrast features.
"""
datadict = {}
spectral_contrast = lr.feature.spectral_contrast(y=data, sr=sr, n_fft=n_fft, hop_length=hop_length)
for var in range(len(spectral_contrast)):
datadict[f'spectral_contrast{var + 1}_mean'] = np.mean(spectral_contrast[var, :])
return datadict
def calculate_tonnetz(self, data, sr):
"""
Calculates tonnetz features from the audio signal.
Parameters:
data (numpy.ndarray): The audio signal.
sr (int): The sampling rate of the audio signal.
Returns:
numpy.ndarray: Tonnetz features.
"""
tonnetz = lr.feature.tonnetz(y=data, sr=sr)
datadict = {}
for var in range(len(tonnetz)):
datadict[f'tonnetz{var + 1}_mean'] = np.mean(tonnetz[var, :])
return datadict
def calculate_spectral_rolloff(self, data, sr, roll_percent=0.85, n_fft=2048, hop_length=512):
"""
Calculates spectral rolloff from the audio signal.
Parameters:
data (numpy.ndarray): The audio signal.
sr (int): The sampling rate of the audio signal.
roll_percent (float): Percentage for determining rolloff.
n_fft (int): The number of points for each FFT.
hop_length (int): The number of samples between successive frames.
Returns:
numpy.ndarray: Spectral rolloff features.
"""
spectral_rolloff = lr.feature.spectral_rolloff(y=data, sr=sr, roll_percent=roll_percent, n_fft=n_fft, hop_length=hop_length)
return spectral_rolloff
def calculate_chroma_features(self, data, sr, n_fft=2048, hop_length=512):
"""
Calculates chroma features from the audio signal.
Parameters:
data (numpy.ndarray): The audio signal.
sr (int): The sampling rate of the audio signal.
n_fft (int): The number of points for each FFT.
hop_length (int): The number of samples between successive frames.
Returns:
numpy.ndarray: Chroma features.
"""
chromagram = chroma_stft(y=data, sr=sr, n_fft=n_fft, hop_length=hop_length)
datadict = {}
for var in range(len(chromagram)):
datadict[f'chromagram{var + 1}_mean'] = np.mean(chromagram[var, :])
return datadict
def calculate_mel_spectral_contrast(self, data, sr, n_fft=2048, hop_length=512):
"""
Calculates mel spectrogram and its contrast from the audio signal.
Parameters:
data (numpy.ndarray): The audio signal.
sr (int): The sampling rate of the audio signal.
n_fft (int): The number of points for each FFT.
hop_length (int): The number of samples between successive frames.
Returns:
numpy.ndarray: Mel spectrogram contrast features.
"""
mel_spectrogram = melspectrogram(y=data, sr=sr, n_fft=n_fft, hop_length=hop_length)
mel_spectral_contrast = lr.feature.spectral_contrast(S=mel_spectrogram)
datadict = {}
for var in range(len(mel_spectral_contrast)):
datadict[f'mel_spectral_contrast{var + 1}_mean'] = np.mean(mel_spectral_contrast[var, :])
return datadict
def calculate_spectral_flatness(self, data, sr, n_fft=2048, hop_length=512):
"""
Calculates spectral flatness from the audio signal.
Parameters:
data (numpy.ndarray): The audio signal.
sr (int): The sampling rate of the audio signal.
n_fft (int): The number of points for each FFT.
hop_length (int): The number of samples between successive frames.
Returns:
numpy.ndarray: Spectral flatness features.
"""
flatness = lr.feature.spectral_flatness(y=data, n_fft=n_fft, hop_length=hop_length)
return flatness
def zero_crossing_rate_features(self, data, n_fft=2048, hop_length=512):
"""
Calculates zero-crossing rate from the audio signal.
Parameters:
data (numpy.ndarray): The audio signal.
n_fft (int): The number of points for each FFT.
hop_length (int): The number of samples between successive frames.
Returns:
numpy.ndarray: Zero-crossing rate features.
"""
zcr = zero_crossing_rate(y=data, frame_length=n_fft, hop_length=hop_length)
return zcr
def rms_energy_features(self, data):
"""
Calculates root mean square (RMS) energy from the audio signal.
Parameters:
data (numpy.ndarray): The audio signal.
Returns:
numpy.ndarray: RMS energy features.
"""
rms_energy = lr.feature.rms(y=data)[0]
return rms_energy
csv_path = "labels_new.csv"
audio_directory_labeled = "labeled"
audio_directory_unlabeled = "unlabeled"
audio_extractor = AudioFeatureExtractor()
# Read the CSV file into a DataFrame
df = pd.read_csv(csv_path)
def process_audio_features(audio_directory, labeled=True, df=df):
# Audio features storage
audio_features_list = []
# Set the target length for audio truncation or padding
lengte = 30 * 22050
audio_arrays = np.empty((len(os.listdir(audio_directory)), lengte))
# Process each audio file
for index, file in enumerate(os.listdir(audio_directory)):
sr = lr.get_samplerate(f'{audio_directory}/{file}')
if file.endswith(".wav"):
# sr = lr.get_samplerate(file)
file_path = os.path.join(audio_directory, file)
data, sfreq = lr.load(file_path, sr=None)
# Truncate or pad the audio
if len(data) > lengte:
# Truncate the data
data = data[:lengte]
elif len(data) < lengte:
# Pad with zeros
padding = lengte - len(data)
data = np.pad(data, (0, padding), mode='constant')
audio_arrays[index] = data
# Extract MFCC features
mfcc_features = audio_extractor.mfccs(data, sfreq)
spectral_contrast_features = audio_extractor.calculate_spectral_contrast(data, sr)
tonnetz_features = audio_extractor.calculate_tonnetz(data, sr)
spectral_rolloff_feature = audio_extractor.calculate_spectral_rolloff(data, sr)
chroma_features = audio_extractor.calculate_chroma_features(data, sr)
mel_spectral_contrast_features = audio_extractor.calculate_mel_spectral_contrast(data, sr)
spectral_flatness_feature = audio_extractor.calculate_spectral_flatness(data, sr)
zero_crossing_feature = audio_extractor.zero_crossing_rate_features(data)
rms_energy = audio_extractor.rms_energy_features(data)
# Combine all features into a dictionary
features_dict = {
'filename': file,
**mfcc_features,
'rms_energy': np.mean(rms_energy),
**spectral_contrast_features,
**tonnetz_features,
'spectral_rolloff': np.mean(spectral_rolloff_feature[0]),
**chroma_features,
**mel_spectral_contrast_features,
'spectral_flatness': np.mean(spectral_flatness_feature[0]),
'zcr': np.mean(zero_crossing_feature[0])
}
# Append the features dictionary to the list
audio_features_list.append(features_dict)
spectograms, spectogram_features = audio_extractor.calculate_spectrograms(audio_arrays)
bandwidths, centroids = audio_extractor.calculate_spectral_features(spectograms)
bandwiths = pd.DataFrame({'bandwith': [np.mean(bandwidth[0]) for bandwidth in bandwidths]})
centroids = pd.DataFrame({'centroid': [np.mean(centroid[0]) for centroid in centroids]})
# Convert the list of feature dictionaries to a DataFrame
audio_features_df = pd.DataFrame(audio_features_list)
audio_features_df = pd.concat([audio_features_df, bandwiths], axis=1)
audio_features_df = pd.concat([audio_features_df, centroids], axis=1)
# Merge the original DataFrame with the new features DataFrame based on the 'filename' column
if labeled:
audio_features_df = pd.merge(df, audio_features_df, on='filename', how='left')
audio_features_df = audio_features_df.sort_values(by='filename')
return audio_features_df
# Process audio features
labeled_df = process_audio_features(audio_directory_labeled)
display(labeled_df)
| filename | genre | mfcc1_mean | mfcc2_mean | mfcc3_mean | mfcc4_mean | mfcc5_mean | mfcc6_mean | mfcc7_mean | mfcc8_mean | ... | mel_spectral_contrast2_mean | mel_spectral_contrast3_mean | mel_spectral_contrast4_mean | mel_spectral_contrast5_mean | mel_spectral_contrast6_mean | mel_spectral_contrast7_mean | spectral_flatness | zcr | bandwith | centroid | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 8 | m00002.wav | jazz | -298.807953 | 112.078209 | 6.485770 | 28.386517 | -6.764679 | 16.651894 | -11.809684 | 12.746783 | ... | 6.739004 | 17.720329 | 31.856210 | 37.582171 | 36.234603 | 42.188262 | 0.001252 | 0.051222 | 1919.917650 | 1451.498371 |
| 9 | m00039.wav | reggae | -169.243668 | 110.447716 | -8.553957 | 43.898693 | 0.266454 | 26.646509 | -14.365674 | 13.026835 | ... | 8.001072 | 15.869485 | 22.225069 | 29.004593 | 27.931632 | 43.075836 | 0.004306 | 0.072178 | 2019.252686 | 1811.358216 |
| 43 | m00041.wav | pop | -18.854591 | 71.328522 | -3.743232 | -1.396592 | 0.710347 | -1.049137 | -1.052407 | -0.249471 | ... | 5.718698 | 13.057337 | 17.657730 | 23.827369 | 27.071292 | 18.570913 | 0.078506 | 0.152910 | 2992.192112 | 3111.061099 |
| 29 | m00072.wav | disco | -69.599335 | 83.059570 | -16.599524 | 0.119469 | 7.415704 | 0.769619 | 1.337008 | 4.690686 | ... | 6.370224 | 12.197484 | 18.810620 | 25.720595 | 24.686535 | 23.377385 | 0.038270 | 0.120259 | 2709.990169 | 2625.095044 |
| 34 | m00096.wav | disco | -91.886307 | 87.604057 | -2.058175 | 34.285538 | -18.153370 | 19.344702 | -14.697328 | 17.116173 | ... | 4.989545 | 15.582052 | 20.384724 | 25.294628 | 29.771765 | 46.579813 | 0.009796 | 0.115890 | 2486.020650 | 2550.135384 |
| 48 | m00102.wav | classical | -436.842285 | 154.113205 | -19.859337 | 20.183603 | 3.164744 | 0.446392 | -6.530639 | -4.603339 | ... | 8.704671 | 18.088766 | 26.164080 | 36.452103 | 37.462534 | 35.556624 | 0.000976 | 0.066325 | 1517.856160 | 1173.931066 |
| 25 | m00112.wav | reggae | -265.694977 | 80.615921 | 9.722022 | 36.657085 | 27.836796 | 12.086828 | 15.014478 | 15.116937 | ... | 3.927251 | 15.154408 | 20.473471 | 26.257647 | 25.445807 | 24.486615 | 0.026549 | 0.060883 | 2595.217468 | 2113.391953 |
| 4 | m00138.wav | reggae | -198.632797 | 102.413582 | -10.031449 | 30.802383 | -3.310606 | 20.276924 | -5.637373 | 28.095631 | ... | 8.111595 | 11.985461 | 21.690643 | 26.647311 | 26.212014 | 47.129611 | 0.005168 | 0.070323 | 2295.466240 | 1995.600514 |
| 5 | m00192.wav | classical | -85.264992 | 118.423058 | -31.472771 | 20.282015 | -4.417709 | 6.922598 | -10.950942 | -1.620085 | ... | 5.707315 | 9.457773 | 16.339001 | 23.798978 | 26.500622 | 37.537164 | 0.010484 | 0.111613 | 1965.028715 | 1878.774030 |
| 22 | m00206.wav | hiphop | -92.591652 | 77.412682 | -32.756371 | 54.596119 | -13.199195 | 33.656281 | -12.085772 | 28.015388 | ... | 3.856905 | 11.629413 | 12.605242 | 16.697020 | 17.101189 | 52.441041 | 0.018014 | 0.157603 | 2295.456105 | 2735.795802 |
| 1 | m00230.wav | country | -89.736382 | 36.286205 | 11.469535 | 37.495590 | 9.199136 | 3.740519 | 2.840358 | 6.811540 | ... | 4.663522 | 12.311560 | 17.618104 | 28.147029 | 26.801658 | 22.182678 | 0.093471 | 0.212375 | 3053.066772 | 3760.424488 |
| 47 | m00236.wav | classical | -368.465942 | 124.265991 | -31.582445 | 17.601763 | 2.322930 | -5.949597 | -11.807772 | -5.547481 | ... | 4.495887 | 16.020693 | 30.754881 | 34.882406 | 36.114791 | 54.128590 | 0.000620 | 0.078817 | 1415.453381 | 1329.264956 |
| 0 | m00248.wav | metal | -75.517509 | 81.911423 | -22.081079 | 69.876999 | -11.740438 | 25.740246 | -18.518965 | 27.027710 | ... | 2.714730 | 9.285961 | 13.318006 | 15.142012 | 17.020385 | 57.419416 | 0.018547 | 0.158776 | 2337.227557 | 2656.165734 |
| 45 | m00253.wav | blues | -3.559072 | 92.927788 | -25.118544 | 45.187210 | -10.871894 | 31.862423 | -18.057922 | 28.628012 | ... | 3.783532 | 12.969313 | 16.648841 | 21.717000 | 24.115583 | 57.660211 | 0.010716 | 0.124735 | 2358.384492 | 2443.238916 |
| 40 | m00298.wav | blues | -213.204529 | 115.154541 | -11.720503 | 39.032555 | -20.357819 | 13.089926 | -9.180815 | 9.023639 | ... | 5.069766 | 14.647256 | 24.722086 | 30.720819 | 27.451555 | 51.615333 | 0.002710 | 0.079215 | 1973.690309 | 1817.529547 |
| 27 | m00313.wav | blues | -249.289398 | 130.987030 | 0.677390 | 66.685783 | 17.897806 | 4.623737 | 6.598308 | 1.249050 | ... | 4.712652 | 16.387888 | 25.459972 | 31.543672 | 29.853833 | 51.528179 | 0.000401 | 0.051725 | 1463.539070 | 1109.721379 |
| 39 | m00338.wav | blues | -55.596630 | 114.951218 | -37.069351 | 64.904381 | -7.164943 | 15.254702 | -16.235331 | 18.643576 | ... | 3.855680 | 11.104764 | 19.421730 | 24.030727 | 23.153801 | 59.228233 | 0.004599 | 0.106627 | 1927.439014 | 1977.108904 |
| 44 | m00339.wav | rock | -70.117538 | 94.181656 | -50.328033 | 46.962898 | -16.114254 | 19.996185 | -23.959724 | 16.344028 | ... | 3.767756 | 8.777708 | 17.115519 | 22.762585 | 21.009458 | 66.166621 | 0.014635 | 0.150945 | 2102.197363 | 2471.302264 |
| 32 | m00351.wav | jazz | -192.517395 | 113.183693 | -6.373058 | 39.593094 | -9.189579 | 17.204056 | -19.114599 | 12.203582 | ... | 4.895479 | 13.100308 | 18.168636 | 31.750680 | 30.777813 | 52.074700 | 0.003388 | 0.076921 | 2107.923976 | 1825.975175 |
| 16 | m00400.wav | blues | -350.358887 | 169.546326 | 31.780231 | 16.713755 | 28.661758 | 19.249090 | 7.846700 | 10.039796 | ... | 6.831016 | 15.706191 | 25.741073 | 31.403125 | 30.358803 | 22.970648 | 0.000457 | 0.021701 | 995.093473 | 570.150688 |
| 13 | m00421.wav | pop | -77.941887 | 32.364956 | 20.077257 | 27.633484 | 16.262774 | 5.319164 | 13.481539 | 3.503227 | ... | 9.366871 | 17.067590 | 22.242897 | 24.953492 | 25.764494 | 21.049781 | 0.066714 | 0.144787 | 3223.867461 | 3727.248835 |
| 6 | m00429.wav | hiphop | -109.509178 | 97.389557 | -20.619621 | 37.366669 | -3.125998 | 28.611204 | -14.169424 | 23.862110 | ... | 4.376860 | 8.659314 | 15.042835 | 21.151530 | 22.051505 | 50.071179 | 0.011507 | 0.104502 | 2327.237804 | 2272.834439 |
| 46 | m00435.wav | classical | -207.377472 | 117.607780 | -41.404255 | 13.253087 | -1.688240 | 15.532319 | -10.362769 | -1.863690 | ... | 4.804461 | 20.265242 | 22.574447 | 30.592474 | 40.035231 | 56.377036 | 0.000801 | 0.108258 | 1551.481235 | 1623.829998 |
| 35 | m00454.wav | hiphop | -103.138268 | 74.090218 | -22.434641 | 51.604790 | -7.079813 | 32.670975 | -14.993524 | 19.642502 | ... | 5.691232 | 11.065545 | 15.903900 | 23.839271 | 22.870837 | 53.006697 | 0.016491 | 0.117624 | 2396.648334 | 2670.154564 |
| 49 | m00477.wav | classical | -412.959259 | 138.519836 | -19.262381 | 34.146679 | 8.975063 | -4.294471 | 4.152584 | 0.881950 | ... | 5.582785 | 20.293131 | 30.609275 | 42.342264 | 38.614245 | 38.829502 | 0.000672 | 0.060885 | 1467.205561 | 1171.844481 |
| 14 | m00501.wav | jazz | -168.123230 | 108.271530 | -14.149940 | 30.457626 | 3.894506 | 4.676564 | 3.187918 | 1.927635 | ... | 5.479137 | 19.986478 | 27.292205 | 31.991843 | 30.909894 | 30.390149 | 0.006512 | 0.067522 | 2091.113741 | 1725.634530 |
| 12 | m00503.wav | metal | -93.591331 | 89.894020 | -55.902695 | 51.637325 | -5.558396 | 28.777815 | -13.892873 | 27.350773 | ... | 6.208451 | 8.601995 | 15.799067 | 22.311950 | 21.688064 | 62.071454 | 0.012679 | 0.151809 | 2037.300179 | 2463.449458 |
| 42 | m00513.wav | pop | -52.649151 | 47.782742 | 13.455156 | 2.213427 | 13.251046 | 9.133875 | 14.447654 | 0.873837 | ... | 7.743124 | 10.976887 | 14.634204 | 21.740248 | 26.191926 | 20.857168 | 0.097539 | 0.210715 | 3426.219520 | 4052.888670 |
| 36 | m00553.wav | disco | -95.103706 | 109.353172 | -30.161179 | 16.358656 | 20.039730 | 11.962816 | 3.485530 | 6.173969 | ... | 4.868121 | 11.508925 | 16.536470 | 23.614719 | 23.721108 | 29.510298 | 0.026017 | 0.103663 | 2143.899287 | 2117.550762 |
| 33 | m00606.wav | country | -171.339005 | 137.354568 | 7.964579 | 28.539564 | 2.708197 | -0.501510 | -2.956100 | -1.159342 | ... | 6.591413 | 10.533838 | 16.756754 | 25.936614 | 26.975167 | 28.856986 | 0.007312 | 0.063856 | 1959.987665 | 1469.784950 |
| 7 | m00623.wav | reggae | -94.140526 | 68.229942 | 3.975480 | 7.631387 | 12.791034 | -3.185735 | -3.907444 | 3.817600 | ... | 7.047003 | 16.691960 | 18.115008 | 23.019129 | 24.171044 | 21.322361 | 0.065537 | 0.136075 | 2974.065401 | 3086.186001 |
| 3 | m00627.wav | metal | -57.683388 | 101.432327 | -41.485245 | 55.130600 | -23.349279 | 28.151102 | -12.139105 | 18.150204 | ... | 4.042038 | 9.291089 | 13.214748 | 17.212025 | 17.637471 | 58.275039 | 0.012321 | 0.141317 | 2092.439557 | 2378.392048 |
| 17 | m00629.wav | country | -82.962616 | 122.532806 | -16.658556 | 40.015911 | -15.007229 | 21.670378 | -18.256283 | 18.361864 | ... | 5.854305 | 15.034976 | 18.742446 | 24.931771 | 25.955064 | 54.375683 | 0.005227 | 0.081104 | 2116.237657 | 1881.161818 |
| 28 | m00633.wav | country | -122.427414 | 111.483139 | -13.694294 | 53.828403 | -2.677765 | 19.677549 | -14.138923 | 13.743676 | ... | 5.908667 | 12.477974 | 21.097610 | 27.547413 | 27.157049 | 52.619927 | 0.005293 | 0.078317 | 2085.606346 | 1879.937791 |
| 2 | m00637.wav | hiphop | -122.780525 | 95.061287 | -29.363251 | 46.780045 | -15.998561 | 27.117586 | -13.113779 | 20.258003 | ... | 6.453961 | 10.992537 | 16.350120 | 21.788517 | 20.466351 | 50.293757 | 0.013041 | 0.113229 | 2181.589027 | 2290.107318 |
| 38 | m00658.wav | hiphop | -105.569511 | 76.674911 | -24.774305 | 55.198990 | -8.257657 | 28.899265 | -15.747581 | 26.304575 | ... | 3.862585 | 12.135674 | 13.885980 | 19.403479 | 20.607843 | 53.621895 | 0.013526 | 0.138555 | 2350.956242 | 2628.976734 |
| 21 | m00671.wav | reggae | -251.392563 | 105.855774 | 2.220024 | 32.484390 | 16.563274 | 8.290815 | 10.365557 | 5.504937 | ... | 6.202627 | 13.453879 | 14.213644 | 19.654592 | 19.496502 | 29.640906 | 0.026613 | 0.089780 | 2298.145722 | 2004.353847 |
| 23 | m00676.wav | pop | 9.675074 | 88.826073 | -20.293680 | 5.101305 | -2.917802 | -0.188181 | 0.327482 | 1.604321 | ... | 3.538988 | 9.555049 | 13.832719 | 17.227212 | 19.715628 | 21.549278 | 0.064364 | 0.131656 | 2559.529362 | 2569.255823 |
| 10 | m00677.wav | country | -139.623062 | 128.793533 | -20.249359 | 49.443615 | -2.160360 | 16.988024 | -8.355296 | 9.818295 | ... | 7.767790 | 18.787435 | 27.903697 | 35.160599 | 34.218542 | 48.088884 | 0.001416 | 0.061745 | 1690.685707 | 1425.263509 |
| 20 | m00678.wav | metal | -95.339104 | 92.066360 | -28.061176 | 52.796284 | -3.018975 | 25.395771 | -6.135991 | 20.098093 | ... | 3.902639 | 12.254983 | 15.608343 | 18.157071 | 18.915123 | 47.654008 | 0.011364 | 0.115765 | 2115.725580 | 2241.454932 |
| 31 | m00716.wav | jazz | -202.608383 | 105.845734 | -20.537838 | 43.897964 | -14.272349 | 25.299541 | -15.592009 | 15.311663 | ... | 5.576754 | 14.930754 | 16.889706 | 26.349590 | 28.195721 | 51.507869 | 0.006012 | 0.093247 | 2084.706315 | 2034.579158 |
| 18 | m00762.wav | disco | -155.637314 | 60.568497 | 23.166864 | 31.186348 | 25.054384 | 16.906994 | 9.438360 | 8.449133 | ... | 4.454963 | 14.698277 | 18.425711 | 22.050855 | 20.513930 | 20.602898 | 0.045092 | 0.101249 | 2990.754025 | 2909.983968 |
| 37 | m00772.wav | rock | -125.065109 | 115.203308 | -48.004681 | 52.843102 | -13.491938 | 21.765408 | -12.428561 | 20.139965 | ... | 5.201100 | 10.631122 | 18.387787 | 22.359313 | 22.331249 | 61.219149 | 0.007513 | 0.121824 | 1926.895810 | 2077.166788 |
| 26 | m00773.wav | pop | -204.752975 | 101.605118 | 26.384224 | 9.185719 | 10.460928 | 5.108919 | -9.447198 | 9.308316 | ... | 9.920602 | 17.031494 | 27.189178 | 34.895090 | 35.677321 | 28.118941 | 0.009270 | 0.075366 | 2559.593931 | 2053.894372 |
| 15 | m00801.wav | rock | -212.298355 | 65.759850 | 45.182362 | 19.730082 | 11.805884 | 8.061574 | 4.434145 | 4.215858 | ... | 7.496245 | 14.080840 | 24.372299 | 29.930723 | 29.264457 | 19.750201 | 0.031043 | 0.108570 | 3203.015264 | 2947.109224 |
| 24 | m00821.wav | metal | -58.720360 | 70.558182 | -19.421354 | 73.593155 | -27.765425 | 23.759441 | -17.904169 | 21.222898 | ... | 3.810858 | 9.925774 | 14.813298 | 17.154393 | 16.498257 | 62.176253 | 0.025555 | 0.196540 | 2358.882414 | 3048.505206 |
| 41 | m00850.wav | disco | -78.351181 | 80.074615 | -9.167377 | 25.477053 | -3.390544 | 16.809401 | 7.270706 | 1.818662 | ... | 3.839945 | 11.835582 | 16.459640 | 24.339468 | 26.110460 | 26.963877 | 0.040865 | 0.126389 | 2533.400412 | 2605.158779 |
| 11 | m00867.wav | rock | -142.442062 | 116.238441 | -32.190319 | 49.114605 | -8.395415 | 22.872288 | -18.311134 | 20.106487 | ... | 7.675207 | 11.516393 | 18.302119 | 25.070244 | 23.581773 | 56.706450 | 0.006455 | 0.097659 | 2068.224879 | 2006.009248 |
| 19 | m00895.wav | rock | -26.406458 | 85.794289 | -16.961445 | 35.260883 | 10.000134 | 10.668921 | 1.446997 | 4.710635 | ... | 4.893592 | 13.844285 | 19.658359 | 25.195343 | 25.510141 | 32.623636 | 0.027207 | 0.115493 | 2378.385172 | 2345.885737 |
| 30 | m00996.wav | jazz | -235.678848 | 144.767654 | -22.600695 | 62.560963 | -9.326273 | 2.016869 | -0.343650 | 2.016511 | ... | 4.571889 | 12.846922 | 19.813868 | 31.435092 | 32.057657 | 49.188174 | 0.001253 | 0.076529 | 1518.994776 | 1338.236233 |
50 rows × 60 columns
#aanpassen
import random
# Functie om een willekeurig muziekfragment af te spelen
def play_random_audio_with_info(audio_directory, labeled_df):
# Lijst van audiobestanden in de opgegeven map
audio_files = [file for file in os.listdir(audio_directory) if file.endswith(".wav")]
# Selecteer een willekeurig audiobestand
random_audio_file = random.choice(audio_files)
# Bepaal het volledige pad naar het geselecteerde bestand
audio_path = os.path.join(audio_directory, random_audio_file)
# Haal het genre op basis van de bestandsnaam uit de labeled_df
genre = labeled_df.loc[labeled_df['filename'] == random_audio_file, 'genre'].values[0]
# Print de bestandsnaam en het genre
print("Bestandsnaam:", random_audio_file)
print("Genre:", genre)
# Speel het audiobestand af
display(Audio(audio_path))
# Speel een willekeurig muziekfragment af uit de gelabelde map
play_random_audio_with_info(audio_directory_labeled, labeled_df)
Bestandsnaam: m00477.wav Genre: classical
unlabeled_df = process_audio_features(audio_directory_unlabeled, labeled=False)
display(unlabeled_df)
| filename | mfcc1_mean | mfcc2_mean | mfcc3_mean | mfcc4_mean | mfcc5_mean | mfcc6_mean | mfcc7_mean | mfcc8_mean | mfcc9_mean | ... | mel_spectral_contrast2_mean | mel_spectral_contrast3_mean | mel_spectral_contrast4_mean | mel_spectral_contrast5_mean | mel_spectral_contrast6_mean | mel_spectral_contrast7_mean | spectral_flatness | zcr | bandwith | centroid | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | m00003.wav | -82.501259 | 97.344116 | -34.373585 | 71.405922 | -3.283182 | 17.367373 | -9.023832 | 16.011181 | -19.003857 | ... | 5.011253 | 13.892055 | 18.007974 | 21.183092 | 21.028454 | 58.034254 | 0.009073 | 0.120159 | 2070.908728 | 2254.451748 |
| 1 | m00012.wav | -1.925411 | 72.695557 | -32.789642 | 63.592033 | -18.557953 | 25.872955 | -13.854105 | 18.064384 | -11.945406 | ... | 6.322091 | 13.544996 | 16.113373 | 22.568365 | 18.241123 | 55.859046 | 0.026390 | 0.178119 | 2286.246872 | 2908.260266 |
| 2 | m00013.wav | -287.520996 | 101.737930 | -35.368999 | 41.282764 | -12.745123 | 17.284992 | -13.978299 | 16.311886 | -5.599029 | ... | 4.346955 | 16.482222 | 24.210026 | 32.560252 | 34.102601 | 59.447519 | 0.002209 | 0.123492 | 1865.851544 | 1953.012399 |
| 3 | m00043.wav | -120.127808 | 91.287666 | -38.794960 | 75.003784 | -3.806012 | 22.666491 | -8.123723 | 23.654572 | -14.638494 | ... | 4.574703 | 13.135090 | 15.795038 | 18.074718 | 19.134837 | 60.384606 | 0.008840 | 0.126103 | 2073.302486 | 2384.812610 |
| 4 | m00044.wav | -437.525208 | 170.971405 | 7.386171 | -3.108705 | 0.777302 | -11.135056 | -12.523807 | -6.900928 | -5.850053 | ... | 4.602050 | 18.591778 | 23.050981 | 33.758989 | 36.850383 | 40.763202 | 0.000153 | 0.052112 | 899.979779 | 790.478225 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 100 | m00971.wav | -246.218369 | 149.443878 | -41.973816 | 11.606413 | -10.287585 | -4.018404 | -7.138945 | -10.137027 | -9.425965 | ... | 6.321750 | 12.820653 | 17.553917 | 24.904399 | 30.941367 | 37.337512 | 0.006206 | 0.091588 | 1588.161024 | 1525.601266 |
| 101 | m00973.wav | -8.531343 | 54.251755 | 20.963310 | 13.099079 | 9.721153 | 6.015052 | 10.720785 | 6.102119 | 0.694264 | ... | 7.653338 | 10.039850 | 19.457696 | 25.698457 | 25.316437 | 18.259208 | 0.088824 | 0.161897 | 3295.553789 | 3671.260489 |
| 102 | m00988.wav | -56.091187 | 36.468166 | 11.945320 | -6.441752 | 3.778163 | 5.284157 | 3.394784 | 4.265098 | 7.993917 | ... | 6.389734 | 16.538572 | 24.927608 | 25.531409 | 23.668680 | 16.240189 | 0.089230 | 0.167399 | 3361.504206 | 3940.349921 |
| 103 | m00991.wav | -406.965424 | 163.139465 | -2.413809 | 32.456650 | 7.907843 | 9.677136 | -5.489037 | 9.523492 | -3.102817 | ... | 8.248197 | 19.474204 | 27.322492 | 31.308818 | 33.020523 | 45.577339 | 0.000300 | 0.044227 | 1404.132189 | 983.761841 |
| 104 | m00995.wav | -223.177246 | 163.246231 | -34.416225 | 24.187868 | -10.304306 | 3.228735 | -12.884593 | 0.805069 | -14.284255 | ... | 7.791964 | 16.950850 | 21.291814 | 29.557188 | 35.280038 | 56.017764 | 0.000566 | 0.071648 | 1371.336609 | 1253.132224 |
105 rows × 59 columns
Voor het maken van het voorspellende model hebben wij feature engineering toegepast op de labeled en unlabeled dataset. De toegevoegde features zijn hierboven te zien. Door het toepassen van feature engineering proberen wij de prestaties van ons voorspellend model te verbeteren. Hieronder zullen wij elke toegevoegde feature toelichten.
Als eerste voegen wij meerder MFCCs toe aan onze dataframe. Dit zijn coëfficiënten die de vorm van het spectrum van geluiden beschrijven. Ze worden berekend door een Fourier-transformatie toe te passen op kleine tijdvensters van het signaal, waarna de logaritme van de amplitudes wordt genomen, gevolgd door een discrete cosinetransformatie. Het resultaat is een reeks coëfficiënten die de frequentie-inhoud van het geluid op een compacte manier weergeven.
Voor het berekenen van de MFCCs worden de volgende 5 stappen doorlopen:
$ x_w[n] = x[n] \cdot w[n] $
Bij deze stap wordt het audio-signaal opgedeeld in kleine tijdvensters, ook wel frames genoemd. Dit helpt bij het vastleggen van de tijdsgebonden eigenschappen van het geluid. Het signaal binnen elk frame wordt vermenigvuldigd met een Hamming-vensterfunctie $ w[n] $ om abrupte overgangen aan het begin en einde van het frame te minimaliseren. Het resultaat is het venstergedragde signaal $ x_w[n] $.
$ X(k) = \text{FFT}(x_w[n]) $
Fast Fourier Transform (FFT): Hier wordt de FFT toegepast op elk venstergedragde signaal $ x_w[n] $. Dit leidt tot de decompositie van het signaal van het tijddomein naar het frequentiedomein, waarbij de amplitudes en fasen van de frequentiecomponenten worden verkregen. De resulterende gegevens worden weergegeven als $ X(k) $, waarbij $ k $ de frequentie-index is.
$ S_m = \sum_{k=0}^{N-1} |X(k)|^2 \cdot H_m(k) $
In deze stap wordt de energie in verschillende frequentiebanden gemeten met behulp van een Mel-filterbank. Elk Mel-filter $ H_m(k) $ is ontworpen om de energie in een bepaald frequentiegebied te vertegenwoordigen volgens de Mel-schaal, die de menselijke waarneming van geluidsfrequentie weergeeft. De energie $ S_m $ in elk Mel-filter wordt berekend door de kwadraten van de magnitude van de FFT-resultaten te vermenigvuldigen met de overeenkomstige filterresponsen en deze op te tellen over alle frequentiebanden.
$ M_m = \log(S_m) $
Na het verkrijgen van de Mel-energieën, worden deze waarden logaritmisch geschaald. Dit wordt gedaan om de dynamische bereik van de gegevens te comprimeren en om de representatie te verbeteren, aangezien mensen logaritmische schalen beter waarnemen dan lineaire schalen. Het resultaat is een reeks logaritmisch geschaalde Mel-energieën $ M_m $.
$ C_l = \sum_{m=0}^{M-1} \cos\left(\frac{\pi l (2m + 1)}{2M}\right) \cdot M_m $
Ten slotte worden de logaritmisch geschaalde Mel-energieën onderworpen aan de DCT. Dit proces vertaalt de gegevens van het frequentiedomein naar het cepstrale domein, waarbij de coëfficiënten $ C_l $ worden verkregen. Deze coëfficiënten representeren verschillende frequentiecomponenten van het geluidsspectrum op een compacte en gestructureerde manier.
Gebruikte Symbolen:
(Deruty, 2022)
Vervolgens voegen wij Root Mean Square energy (RMS energy) toe. Deze feature geeft aan hoeveel energie het signaal gemiddeld bevat. Bij ons gaat het hier om het geluidssignaal van muzieknummers. Aan de hand van de RMS energy kan de intensiteit van het signaal makkelijk worden beoordeeld. Hoe hoger de RMS energy, hoe luider het signaal gemiddeld is.
Voor het berekenen van de RMS energy nemen wij de RMS van het muzieksignaal. Dit gaat als volgt:
Kwadrateer elk monster $ x[n] $ in het signaal: $ x^2[n] $
Bereken het gemiddelde van deze gekwadrateerde monsters over de hele periode $ N $: $ \text{Gemiddelde} = \frac{1}{N} \sum_{n=0}^{N-1} x^2[n] $
Neem de vierkantswortel van dit gemiddelde: $ \text{RMS} = \sqrt{\text{Gemiddelde}} $
(Hathaway, 2005)
We voegen ook spectral contrast toe, een functie die het verschil in amplitude tussen pieken en dalen in een frequentiespectrum meet. Dit biedt inzicht in het perceptuele contrast tussen spectrale pieken en achtergrondgeluid, wat informatie oplevert over de toonkwaliteit van het geluid, in ons geval over verschillende muziekfragmenten.
De waarde van spectral contrast wordt bepaald door eerst het frequentiespectrum van het geluidssignaal op te splitsen in verschillende frequentiebanden. Vervolgens wordt voor elke frequentieband het contrast berekend tussen het gemiddelde energieniveau van die band en het gemiddelde energieniveau van aangrenzende frequentiebanden. Dit contrast wordt genormaliseerd om rekening te houden met verschillen in de absolute energieniveaus van het geluidssignaal. Ten slotte worden de resulterende waarden voor elke frequentieband samengevoegd tot een enkel kenmerk dat de mate van variabiliteit in het geluidsspectrum weergeeft.
Formule spectral contrast:
$$ C_m = \sum_{k=1}^{K} \left| X(k) \right| \cdot \left| X(k) - X_{\text{min}}(k) \right| $$waarbij:
(Librosa.Feature.Spectral_Contrast — Librosa 0.10.1 Documentation, z.d.)
Tonnetz is een concept uit de muziektheorie dat de harmonische relaties tussen tonen en akkoorden visualiseert door middel van een zeshoekig rooster of diagram, vergelijkbaar met een muzikale kaart waarop de onderlinge verbanden tussen verschillende tonen en akkoorden worden weergegeven.
De waarde van Tonnetz wordt bepaald door de berekening van de afstanden tussen punten op het rooster, wat de mate van harmonische verwantschap aangeeft. Deze berekening maakt gebruik van muziektheoretische concepten, zoals toonafstanden en intervallen, om de harmonische relaties te definiëren.
Punten die dicht bij elkaar liggen op het Tonnetz-rooster vertegenwoordigen sterke harmonische verbindingen, terwijl punten die verder uit elkaar liggen minder nauw verbonden zijn harmonisch gezien. De analyse van Tonnetz biedt inzicht in de harmonische structuur en relaties binnen een muziekstuk, wat van belang kan zijn voor ons voorspellend model.
In ons project maken we gebruik van de librosa-module om de Tonnetz te bepalen. Eerst wordt het audiosignaal omgezet naar een spectrogram, waarna chromagramfuncties worden berekend. De afstanden tussen de chromagrampunten worden vervolgens omgezet naar een zeshoekig Tonnetz-rooster met behulp van een transformatiematrix die de relaties tussen noten weergeeft. Uiteindelijk kan hiermee een visuele weergave worden getoond, waardoor we de muzikale structuur en harmonische samenhang van het signaal kunnen analyseren.
Verder is er geen specifieke formule voor het berekenen van Tonnetz, omdat het een conceptueel model is dat gebaseerd is op muziektheoretische principes en geometrische representatie.
(Librosa.Feature.Tonnetz — Librosa 0.10.1 Documentation, z.d.)
Het spectral rolloff is eenvoudigweg de frequentie die het frequentiegebied onder een bepaald percentage van de totale spectrale energie verdeelt, meestal is dit bij 85%. Bovendien dient het als een indicator van de mate van verandering in spectrale energie naarmate de frequentie toeneemt, waardoor het informatie verschaft over de steilheid van het spectrum van een geluidssignaal.
De formule is gegeven door:
$ R = \frac{\sum_{f} S(f)}{\sum_{f} S(f_{\text{totaal}})} \cdot 100 \leq p $
(Librosa.Feature.Spectral_Rolloff — Librosa 0.10.1 Documentation, z.d.)
Chroma-kenmerken bieden inzicht in de toonhoogteverdeling in muziek, waarbij de tonale kwaliteiten worden benadrukt. Het chromagram, een grafische weergave van de chroma-kenmerken, deelt het muzikale octaaf op in 12 gelijke delen, die overeenkomen met de 12 muzikale toonhoogteklassen: {C, C♯, D, D♯, E, F, F♯, G, G♯, A, A♯, B}
De chroma-Features worden berekend met behulp van het chromagram, waarbij elke chromawaarde (C_i) wordt bepaald door de som van de magnitudes van de frequentiecomponenten die overeenkomen met de betreffende toonhoogteklasse. Met andere woorden, voor elke toonhoogteklasse wordt de magnitude van alle frequentiecomponenten die in die klasse vallen opgeteld.(Wikipedia contributors, 2024)
De formule om de chromawaarde $ C_i $ te berekenen is:
$ C_i = \sum_{j} \text{magnitude}(f_j) $
Hierbij staat $ C_i $ voor de chromawaarde voor de $ i $-de toonhoogteklasse, en magnitude$ \text{magnitude}(f_j) $ staat voor de magnitude van de $ j $-de frequentiecomponent in het spectrum die overeenkomt met de betreffende toonhoogteklasse. De sommatie wordt uitgevoerd over alle frequentiecomponenten die overeenkomen met de $ i $-de toonhoogteklasse.
Dit proces wordt herhaald voor elk van de twaalf toonhoogteklassen om de complete chroma-kenmerken te verkrijgen.
We voegen ook Mel Spectral Contrast features toe, een functie die het verschil in amplitude tussen pieken en dalen in een frequentiespectrum meet, maar dan op basis van de Mel-schaal. Dit biedt inzicht in het perceptuele contrast tussen spectrale pieken en achtergrondgeluid, waardoor we informatie verkrijgen over de toonkwaliteit van het geluid, met name voor verschillende muziekfragmenten.
De waarde van Mel Spectral Contrast wordt bepaald door eerst het frequentiespectrum van het geluidssignaal om te zetten naar de Mel-schaal. Vervolgens wordt voor elke Mel-frequentieband het contrast berekend tussen het gemiddelde energieniveau van die band $ \mu_m $ en het gemiddelde energieniveau van aangrenzende Mel-frequentiebanden. Dit contrast wordt gewogen met het kwadraat van de afstand tot het gemiddelde $ (m - \mu_m)^2 $ en genormaliseerd om rekening te houden met verschillen in de absolute energieniveaus van het geluidssignaal. Ten slotte worden de resulterende waarden voor elke Mel-frequentieband samengevoegd tot een enkel kenmerk dat de mate van variabiliteit in het geluidsspectrum weergeeft. Dit kenmerk voegen wij uiteindelijk toe aan het dataframe.(Verma, 2021)
Formule voor mel spectral contrast:
$$ text{Mel_Spectral_Contrast}(X) = \frac{\sum_{m=1}^{M} (m - \mu_m)^2 \cdot S_m}{\sum_{m=1}^{M} S_m} $$Spectral Flatness is een audiokenmerk dat de mate van variabiliteit in het frequentiespectrum van een geluidssignaal beschrijft. Het geeft aan hoe gelijkmatig de energie verdeeld is over de frequentiebanden in het spectrum. Een hoge waarde voor Spectral Flatness suggereert een gelijkmatige verdeling van energie over het spectrum, wat kan duiden op een geluidssignaal met een breed frequentiebereik en een gebrek aan dominante frequentiepieken. Aan de andere kant duidt een lage waarde op een sterk piekachtig spectrum, waarbij de energie geconcentreerd is rond specifieke frequenties.
De waarde van Spectral Flatness wordt berekend door de meetkundige gemiddelde (GM) te delen door het rekenkundige gemiddelde (AM) van de amplitudes van de frequentiecomponenten in het spectrum. Met andere woorden, het wordt berekend als de verhouding tussen het gemiddelde van de logaritmische amplitudes en de logaritmische amplitude van het gemiddelde. Deze verhouding wordt vaak genormaliseerd om waarden tussen 0 en 1 te krijgen, waarbij een waarde dichter bij 1 wijst op een vlakker spectrum en een waarde dichter bij 0 op een meer piekachtig spectrum.(Wikipedia contributors, 2023)
In formulevorm kan Spectral Flatness worden uitgedrukt als: $$ \text{Spectral Flatness} = \frac{{\exp\left(\frac{1}{N} \sum_{i=1}^{N} \ln(A_i)\right)}}{{\frac{1}{N} \sum_{i=1}^{N} A_i}} $$
Waarbij $ (A_i) $ de amplitude van de $i$-de frequentiecomponent is en $N$ het totale aantal frequentiecomponenten in het spectrum.
Zero Crossing Rate (ZCR) is een audiokenmerk dat de frequentie van signaalovergangen door nul in een geluidssignaal meet. Het houdt rekening met het aantal keren dat het signaal de horizontale as kruist en geeft daarmee een indicatie van de veranderingen in het signaal over de tijd. Een hogere ZCR duidt op meer veranderingen in het signaal en kan worden geassocieerd met geluiden met een hogere mate van dynamiek of ruwheid, wat waardevolle informatie biedt over de aard en complexiteit van het geluidssignaal.
De Zero Crossing Rate wordt berekend met behulp van de formule:
$$ \text{ZCR} = \frac{1}{N-1} \sum_{n=1}^{N-1} | \text{sign}(x[n]) - \text{sign}(x[n-1]) | $$Hierbij staat $ N $ voor het aantal samples in het signaal en $ x[n] $ voor de waarde van het signaal op het tijdstip $ n $. De ZCR geeft het gemiddelde aantal keren aan waarop het signaal de waarde nul kruist per tijdsinterval, wat een indicatie kan zijn van de mate van verandering of activiteit in het signaal.(Torres-García et al., 2022)
Bandbreedte, ook wel bekend als Bandwidth, refereert naar het bereik van frequenties binnen een signaal of een frequentiespectrum. Het indiceert hoeveel ruimte een signaal beslaat op de frequentieschaal en wordt uitgedrukt in hertz (Hz). Een brede bandbreedte suggereert dat het signaal een uitgebreid frequentiebereik omvat, terwijl een smalle bandbreedte aanduidt dat het signaal beperkt is tot een klein frequentiebereik.
De waarde van de bandbreedte wordt vastgesteld door het verschil te berekenen tussen de hoogste en laagste frequentiecomponenten in het signaal of frequentiespectrum. Dit kan worden uitgedrukt door de frequentie van het hoogste punt in het spectrum te verminderen met de frequentie van het laagste punt. In een frequentiespectrum wordt de bandbreedte beïnvloed door de breedte van de pieken die de energie van het signaal op verschillende frequenties weergeven. Een bredere piek duidt op een grotere bandbreedte, terwijl een smallere piek wijst op een kleinere bandbreedte.
De formule voor het berekenen van de bandbreedte $ B $ is:
$$ B = f_{\text{max}} - f_{\text{min}} $$Waarbij $ f_{\text{max}} $ de frequentie van het hoogste punt in het spectrum vertegenwoordigt, en $ f_{\text{min}} $ de frequentie van het laagste punt in het spectrum.
Centroids, in de context van signaalverwerking en akoestische analyse, zijn maatstaven die worden gebruikt om de centrale frequentie van een signaal of een frequentiespectrum te kwantificeren. Het concept van een centroid komt voort uit de statistiek, waar het verwijst naar het massamiddelpunt van een geometrische vorm.
In de context van akoestische analyse, vertegenwoordigt de centroid de gemiddelde frequentie van een geluidssignaal. Het is een belangrijk kenmerk dat informatie geeft over waar de meeste energie in het frequentiespectrum van het signaal geconcentreerd is. De centroid kan bijvoorbeeld aangeven of een geluidssignaal eerder laagfrequent (lage centroid) of hoogfrequent (hoge centroid) is.(Wikipedia contributors, 2024a)
Hieronder staat de formule voor het berekenen van de centroid.
De formule voor het berekenen van de centroid ($ C $) is:
$$ C = \frac{\sum_{i} f_i \cdot A_i}{\sum_{i} A_i} $$def scaler(df, labeled=True):
"""
Normalizes numeric columns of a DataFrame using sklearn MinMaxScaler
Parameters:
- df (pd.DataFrame): Input DataFrame containing numeric columns to be standardized.
Returns:
- pd.DataFrame: A new DataFrame with standardized numeric columns.
"""
scaler = MinMaxScaler()
if labeled:
cols = ['filename', 'genre']
else:
cols = ['filename']
scaled_df = df[df.columns.difference(cols)]
scaled_df = pd.DataFrame(scaler.fit_transform(scaled_df))
scaled_df.columns = df[df.columns.difference(cols)].columns
scaled_df = pd.concat([pd.DataFrame(df[cols]), scaled_df], axis=1)
return scaled_df
df = scaler(unlabeled_df, labeled=False)
display(df.head())
| filename | bandwith | centroid | chromagram10_mean | chromagram11_mean | chromagram12_mean | chromagram1_mean | chromagram2_mean | chromagram3_mean | chromagram4_mean | ... | spectral_contrast7_mean | spectral_flatness | spectral_rolloff | tonnetz1_mean | tonnetz2_mean | tonnetz3_mean | tonnetz4_mean | tonnetz5_mean | tonnetz6_mean | zcr | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | m00003.wav | 0.448700 | 0.463313 | 0.536488 | 0.723331 | 0.959317 | 0.760275 | 0.628028 | 0.688307 | 0.598168 | ... | 0.833694 | 0.075079 | 0.446538 | 0.601636 | 0.327193 | 0.433945 | 0.462291 | 0.286771 | 0.359017 | 0.485893 |
| 1 | m00012.wav | 0.531218 | 0.660143 | 0.431423 | 0.385958 | 0.370729 | 0.728339 | 0.920078 | 0.984592 | 0.734350 | ... | 0.892147 | 0.220823 | 0.583361 | 0.565916 | 0.462638 | 0.419674 | 0.263680 | 0.141557 | 0.452145 | 0.803681 |
| 2 | m00013.wav | 0.370122 | 0.372563 | 0.584292 | 0.383882 | 0.094401 | 0.600906 | 0.101713 | 0.107339 | 0.045195 | ... | 0.666645 | 0.017305 | 0.366321 | 0.539972 | 0.673517 | 0.074136 | 0.513645 | 0.213762 | 0.537025 | 0.504171 |
| 3 | m00043.wav | 0.449617 | 0.502558 | 0.360861 | 0.606008 | 0.721541 | 0.650086 | 0.515102 | 0.610834 | 0.835636 | ... | 0.809051 | 0.073118 | 0.473765 | 0.552052 | 0.282639 | 0.611838 | 0.573084 | 0.650816 | 0.246407 | 0.518485 |
| 4 | m00044.wav | 0.000000 | 0.022579 | 0.115212 | 0.573531 | 0.077500 | 0.000000 | 0.021968 | 0.402056 | 0.456909 | ... | 0.110577 | 0.000000 | 0.016254 | 0.234122 | 0.581224 | 0.558948 | 0.000000 | 0.204898 | 0.412068 | 0.112807 |
5 rows × 59 columns
df.drop("filename", axis=1, inplace=True)
df
| bandwith | centroid | chromagram10_mean | chromagram11_mean | chromagram12_mean | chromagram1_mean | chromagram2_mean | chromagram3_mean | chromagram4_mean | chromagram5_mean | ... | spectral_contrast7_mean | spectral_flatness | spectral_rolloff | tonnetz1_mean | tonnetz2_mean | tonnetz3_mean | tonnetz4_mean | tonnetz5_mean | tonnetz6_mean | zcr | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0.448700 | 0.463313 | 0.536488 | 0.723331 | 0.959317 | 0.760275 | 0.628028 | 0.688307 | 0.598168 | 0.561027 | ... | 0.833694 | 0.075079 | 0.446538 | 0.601636 | 0.327193 | 0.433945 | 0.462291 | 0.286771 | 0.359017 | 0.485893 |
| 1 | 0.531218 | 0.660143 | 0.431423 | 0.385958 | 0.370729 | 0.728339 | 0.920078 | 0.984592 | 0.734350 | 0.421036 | ... | 0.892147 | 0.220823 | 0.583361 | 0.565916 | 0.462638 | 0.419674 | 0.263680 | 0.141557 | 0.452145 | 0.803681 |
| 2 | 0.370122 | 0.372563 | 0.584292 | 0.383882 | 0.094401 | 0.600906 | 0.101713 | 0.107339 | 0.045195 | 0.394422 | ... | 0.666645 | 0.017305 | 0.366321 | 0.539972 | 0.673517 | 0.074136 | 0.513645 | 0.213762 | 0.537025 | 0.504171 |
| 3 | 0.449617 | 0.502558 | 0.360861 | 0.606008 | 0.721541 | 0.650086 | 0.515102 | 0.610834 | 0.835636 | 1.000000 | ... | 0.809051 | 0.073118 | 0.473765 | 0.552052 | 0.282639 | 0.611838 | 0.573084 | 0.650816 | 0.246407 | 0.518485 |
| 4 | 0.000000 | 0.022579 | 0.115212 | 0.573531 | 0.077500 | 0.000000 | 0.021968 | 0.402056 | 0.456909 | 0.020207 | ... | 0.110577 | 0.000000 | 0.016254 | 0.234122 | 0.581224 | 0.558948 | 0.000000 | 0.204898 | 0.412068 | 0.112807 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 100 | 0.263711 | 0.243890 | 0.265539 | 0.359021 | 0.159503 | 0.468268 | 0.266454 | 0.704754 | 0.361255 | 0.358404 | ... | 0.101925 | 0.050949 | 0.226399 | 0.622226 | 0.693546 | 0.459072 | 0.276723 | 0.567309 | 0.326597 | 0.329244 |
| 101 | 0.917984 | 0.889847 | 0.497698 | 0.499467 | 0.558340 | 0.483318 | 0.761525 | 0.645451 | 0.501318 | 0.455329 | ... | 0.046845 | 0.746303 | 0.913696 | 0.645293 | 0.282011 | 0.376291 | 0.050440 | 0.469340 | 0.408466 | 0.714738 |
| 102 | 0.943256 | 0.970857 | 0.667814 | 0.794760 | 0.763969 | 0.727771 | 0.644380 | 0.533659 | 0.477373 | 0.326759 | ... | 0.023429 | 0.749720 | 0.964501 | 0.373759 | 0.315903 | 0.546494 | 0.660520 | 0.155468 | 0.169731 | 0.744902 |
| 103 | 0.193191 | 0.080768 | 0.160092 | 0.553143 | 0.150116 | 0.016812 | 0.003486 | 0.402058 | 0.896679 | 0.238091 | ... | 0.411653 | 0.001241 | 0.108823 | 0.000000 | 0.587919 | 0.992714 | 0.133532 | 0.632113 | 0.972459 | 0.069575 |
| 104 | 0.180624 | 0.161863 | 0.248791 | 0.448866 | 0.112806 | 0.249699 | 0.316415 | 0.632128 | 0.315825 | 0.031996 | ... | 0.609460 | 0.003478 | 0.167655 | 0.498418 | 0.556749 | 0.620428 | 0.040981 | 0.535506 | 0.335021 | 0.219916 |
105 rows × 58 columns
# overgenomen uit ml les
inertia = []
k = range(1, 11)
for i in k:
model = KMeans(n_clusters=i, n_init=10)
model.fit(df)
inertia.append(model.inertia_)
plt.plot(k, inertia, '-x')
plt.xlabel('Aantal (k) clusters')
plt.ylabel('inertia')
plt.xticks(k)
plt.show()
C:\Users\jesse\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1436: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1. warnings.warn( C:\Users\jesse\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1436: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1. warnings.warn( C:\Users\jesse\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1436: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1. warnings.warn( C:\Users\jesse\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1436: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1. warnings.warn( C:\Users\jesse\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1436: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1. warnings.warn( C:\Users\jesse\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1436: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1. warnings.warn( C:\Users\jesse\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1436: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1. warnings.warn( C:\Users\jesse\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1436: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1. warnings.warn( C:\Users\jesse\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1436: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1. warnings.warn( C:\Users\jesse\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1436: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1. warnings.warn(
Nu voeren we Kmeans clustering uit om zo een visualisatie van de inertia te krijgen. Inertia is een manier om te achterhalen hoeveel clusters we moeten gebruiken, door het te visualiseren kunnen we gemakkelijk zien wat de beste waarde is. hier kunnen we zien dat het elleboog op het punt k = 3 staat. dit betekent dat de beste aantal clusters 3 is. de reden dat het elleboog punt het beste kan worden gebruikt is omdat hier het balans ligt tussen minimale afstanden van punten tot het centrum van hun cluster en overfitting. als het gekozen punt verhoogt wordt betekent dit dus dat de prestaties van het model op de training set misschien verhoogt worden maar niet op de test set het verlagen is natuurlijk ook niet aan te raden sinds zelfs het verlagen van 3 naar 2 al een grootte impact heeft op de waarde van de inertia en dus spreiding van de punten tot hun cluster centrum.
data = df
data
| bandwith | centroid | chromagram10_mean | chromagram11_mean | chromagram12_mean | chromagram1_mean | chromagram2_mean | chromagram3_mean | chromagram4_mean | chromagram5_mean | ... | spectral_contrast7_mean | spectral_flatness | spectral_rolloff | tonnetz1_mean | tonnetz2_mean | tonnetz3_mean | tonnetz4_mean | tonnetz5_mean | tonnetz6_mean | zcr | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0.448700 | 0.463313 | 0.536488 | 0.723331 | 0.959317 | 0.760275 | 0.628028 | 0.688307 | 0.598168 | 0.561027 | ... | 0.833694 | 0.075079 | 0.446538 | 0.601636 | 0.327193 | 0.433945 | 0.462291 | 0.286771 | 0.359017 | 0.485893 |
| 1 | 0.531218 | 0.660143 | 0.431423 | 0.385958 | 0.370729 | 0.728339 | 0.920078 | 0.984592 | 0.734350 | 0.421036 | ... | 0.892147 | 0.220823 | 0.583361 | 0.565916 | 0.462638 | 0.419674 | 0.263680 | 0.141557 | 0.452145 | 0.803681 |
| 2 | 0.370122 | 0.372563 | 0.584292 | 0.383882 | 0.094401 | 0.600906 | 0.101713 | 0.107339 | 0.045195 | 0.394422 | ... | 0.666645 | 0.017305 | 0.366321 | 0.539972 | 0.673517 | 0.074136 | 0.513645 | 0.213762 | 0.537025 | 0.504171 |
| 3 | 0.449617 | 0.502558 | 0.360861 | 0.606008 | 0.721541 | 0.650086 | 0.515102 | 0.610834 | 0.835636 | 1.000000 | ... | 0.809051 | 0.073118 | 0.473765 | 0.552052 | 0.282639 | 0.611838 | 0.573084 | 0.650816 | 0.246407 | 0.518485 |
| 4 | 0.000000 | 0.022579 | 0.115212 | 0.573531 | 0.077500 | 0.000000 | 0.021968 | 0.402056 | 0.456909 | 0.020207 | ... | 0.110577 | 0.000000 | 0.016254 | 0.234122 | 0.581224 | 0.558948 | 0.000000 | 0.204898 | 0.412068 | 0.112807 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 100 | 0.263711 | 0.243890 | 0.265539 | 0.359021 | 0.159503 | 0.468268 | 0.266454 | 0.704754 | 0.361255 | 0.358404 | ... | 0.101925 | 0.050949 | 0.226399 | 0.622226 | 0.693546 | 0.459072 | 0.276723 | 0.567309 | 0.326597 | 0.329244 |
| 101 | 0.917984 | 0.889847 | 0.497698 | 0.499467 | 0.558340 | 0.483318 | 0.761525 | 0.645451 | 0.501318 | 0.455329 | ... | 0.046845 | 0.746303 | 0.913696 | 0.645293 | 0.282011 | 0.376291 | 0.050440 | 0.469340 | 0.408466 | 0.714738 |
| 102 | 0.943256 | 0.970857 | 0.667814 | 0.794760 | 0.763969 | 0.727771 | 0.644380 | 0.533659 | 0.477373 | 0.326759 | ... | 0.023429 | 0.749720 | 0.964501 | 0.373759 | 0.315903 | 0.546494 | 0.660520 | 0.155468 | 0.169731 | 0.744902 |
| 103 | 0.193191 | 0.080768 | 0.160092 | 0.553143 | 0.150116 | 0.016812 | 0.003486 | 0.402058 | 0.896679 | 0.238091 | ... | 0.411653 | 0.001241 | 0.108823 | 0.000000 | 0.587919 | 0.992714 | 0.133532 | 0.632113 | 0.972459 | 0.069575 |
| 104 | 0.180624 | 0.161863 | 0.248791 | 0.448866 | 0.112806 | 0.249699 | 0.316415 | 0.632128 | 0.315825 | 0.031996 | ... | 0.609460 | 0.003478 | 0.167655 | 0.498418 | 0.556749 | 0.620428 | 0.040981 | 0.535506 | 0.335021 | 0.219916 |
105 rows × 58 columns
| Player | Speed | Defence | Pas | Shot | Creativeness |
|---|---|---|---|---|---|
| Vikram | 90 | 70 | 80 | 75 | 85 |
| Bob | 60 | 90 | 50 | 40 | 50 |
| Mark | 80 | 65 | 90 | 70 | 80 |
| Sami | 95 | 40 | 60 | 85 | 70 |
| Daan | - | 85 | - | - | - |
| Penaldo | 75 | 30 | 60 | 95 | 40 |
| Pessi | 70 | 50 | 85 | 60 | 90 |
Kies het aantal clusters (K) dat je wilt creëren in je dataset. Initialiseerd de centroids willekeurig. Deze centroids vertegenwoordigen de initiële centroid van de clusters. Toewijzingsstap:
Voor elk datapunt in de dataset, bereken de afstand tot elk centroid. Wijs het datapunt toe aan de cluster waarvan de centroid het dichtstbij is met behulp van de Euclidische afstand.
Herbereken de centroids van elke cluster door het gemiddelde te nemen van alle datapunten die aan die cluster zijn toegewezen.
Herhaal de toewijzings- en updatestappen totdat convergentie is bereikt. Convergentie treedt op wanneer de centroids niet significant meer veranderen of wanneer een bepaald aantal iteraties is bereikt. Output:
Het algoritme geeft K clusters uit, elk gerepresenteerd door zijn centroid.
Opmerking: Ondanks dat Daan NaN-waarden heeft, zal hij toch worden toegewezen aan een centrum op basis van bestaande kenmerken.
class Clustering:
def __init__(self, data):
"""
Initializes the Clustering object with input data.
Parameters:
- data (numpy.ndarray): Input data for clustering.
"""
self.data = data
self.cluster_labels = None
def calculate_silhouette_score(self):
if self.cluster_labels is not None:
if len(np.unique(self.cluster_labels)) > 1:
self.silhouette_score = silhouette_score(self.data, self.cluster_labels)
else:
print("Silhouette score cannot be calculated with only one cluster.")
else:
print("Cluster labels not available. Run a clustering algorithm first.")
def cluster_kmeans(self, n_clusters=3):
"""
Performs KMeans clustering on the input data.
Parameters:
- n_clusters (int): Number of clusters.
Returns:
- numpy.ndarray: An array containing the input data and assigned cluster labels.
"""
kmeans = KMeans(n_clusters=n_clusters, random_state=42)
self.cluster_labels = kmeans.fit_predict(self.data)
return np.column_stack((self.data, self.cluster_labels))
def cluster_agglomerative(self, n_clusters=3):
"""
Performs Agglomerative clustering on the input data.
Parameters:
- n_clusters (int): Number of clusters.
Returns:
- numpy.ndarray: An array containing the input data and assigned cluster labels.
"""
agglomerative = AgglomerativeClustering(n_clusters=n_clusters)
self.cluster_labels = agglomerative.fit_predict(self.data)
return np.column_stack((self.data, self.cluster_labels))
def cluster_dbscan(self, eps=0.5, min_samples=5):
"""
Performs DBSCAN clustering on the input data.
Parameters:
- eps (float): The maximum distance between two samples for one to be considered as in the neighborhood of the other.
- min_samples (int): The number of samples (or total weight) in a neighborhood for a point to be considered as a core point.
Returns:
- numpy.ndarray: An array containing the input data and assigned cluster labels.
"""
dbscan = DBSCAN(eps=eps, min_samples=min_samples)
self.cluster_labels = dbscan.fit_predict(self.data)
return np.column_stack((self.data, self.cluster_labels))
def cluster_birch(self, n_clusters=3):
"""
Performs Birch clustering on the input data.
Parameters:
- n_clusters (int): Number of clusters.
Returns:
- numpy.ndarray: An array containing the input data and assigned cluster labels.
"""
birch = Birch(n_clusters=n_clusters)
self.cluster_labels = birch.fit_predict(self.data)
return np.column_stack((self.data, self.cluster_labels))
def cluster_meanshift(self, bandwidth=0.5):
"""
Performs MeanShift clustering on the input data.
Parameters:
- bandwidth (float): Bandwidth parameter for MeanShift.
Returns:
- numpy.ndarray: An array containing the input data and assigned cluster labels.
"""
meanshift = MeanShift(bandwidth=bandwidth)
self.cluster_labels = meanshift.fit_predict(self.data)
return np.column_stack((self.data, self.cluster_labels))
unlabeled_data = data
unlabeled_data
| bandwith | centroid | chromagram10_mean | chromagram11_mean | chromagram12_mean | chromagram1_mean | chromagram2_mean | chromagram3_mean | chromagram4_mean | chromagram5_mean | ... | spectral_contrast7_mean | spectral_flatness | spectral_rolloff | tonnetz1_mean | tonnetz2_mean | tonnetz3_mean | tonnetz4_mean | tonnetz5_mean | tonnetz6_mean | zcr | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0.448700 | 0.463313 | 0.536488 | 0.723331 | 0.959317 | 0.760275 | 0.628028 | 0.688307 | 0.598168 | 0.561027 | ... | 0.833694 | 0.075079 | 0.446538 | 0.601636 | 0.327193 | 0.433945 | 0.462291 | 0.286771 | 0.359017 | 0.485893 |
| 1 | 0.531218 | 0.660143 | 0.431423 | 0.385958 | 0.370729 | 0.728339 | 0.920078 | 0.984592 | 0.734350 | 0.421036 | ... | 0.892147 | 0.220823 | 0.583361 | 0.565916 | 0.462638 | 0.419674 | 0.263680 | 0.141557 | 0.452145 | 0.803681 |
| 2 | 0.370122 | 0.372563 | 0.584292 | 0.383882 | 0.094401 | 0.600906 | 0.101713 | 0.107339 | 0.045195 | 0.394422 | ... | 0.666645 | 0.017305 | 0.366321 | 0.539972 | 0.673517 | 0.074136 | 0.513645 | 0.213762 | 0.537025 | 0.504171 |
| 3 | 0.449617 | 0.502558 | 0.360861 | 0.606008 | 0.721541 | 0.650086 | 0.515102 | 0.610834 | 0.835636 | 1.000000 | ... | 0.809051 | 0.073118 | 0.473765 | 0.552052 | 0.282639 | 0.611838 | 0.573084 | 0.650816 | 0.246407 | 0.518485 |
| 4 | 0.000000 | 0.022579 | 0.115212 | 0.573531 | 0.077500 | 0.000000 | 0.021968 | 0.402056 | 0.456909 | 0.020207 | ... | 0.110577 | 0.000000 | 0.016254 | 0.234122 | 0.581224 | 0.558948 | 0.000000 | 0.204898 | 0.412068 | 0.112807 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 100 | 0.263711 | 0.243890 | 0.265539 | 0.359021 | 0.159503 | 0.468268 | 0.266454 | 0.704754 | 0.361255 | 0.358404 | ... | 0.101925 | 0.050949 | 0.226399 | 0.622226 | 0.693546 | 0.459072 | 0.276723 | 0.567309 | 0.326597 | 0.329244 |
| 101 | 0.917984 | 0.889847 | 0.497698 | 0.499467 | 0.558340 | 0.483318 | 0.761525 | 0.645451 | 0.501318 | 0.455329 | ... | 0.046845 | 0.746303 | 0.913696 | 0.645293 | 0.282011 | 0.376291 | 0.050440 | 0.469340 | 0.408466 | 0.714738 |
| 102 | 0.943256 | 0.970857 | 0.667814 | 0.794760 | 0.763969 | 0.727771 | 0.644380 | 0.533659 | 0.477373 | 0.326759 | ... | 0.023429 | 0.749720 | 0.964501 | 0.373759 | 0.315903 | 0.546494 | 0.660520 | 0.155468 | 0.169731 | 0.744902 |
| 103 | 0.193191 | 0.080768 | 0.160092 | 0.553143 | 0.150116 | 0.016812 | 0.003486 | 0.402058 | 0.896679 | 0.238091 | ... | 0.411653 | 0.001241 | 0.108823 | 0.000000 | 0.587919 | 0.992714 | 0.133532 | 0.632113 | 0.972459 | 0.069575 |
| 104 | 0.180624 | 0.161863 | 0.248791 | 0.448866 | 0.112806 | 0.249699 | 0.316415 | 0.632128 | 0.315825 | 0.031996 | ... | 0.609460 | 0.003478 | 0.167655 | 0.498418 | 0.556749 | 0.620428 | 0.040981 | 0.535506 | 0.335021 | 0.219916 |
105 rows × 58 columns
k = 3
kmeans = KMeans(n_clusters=k, n_init=10, random_state=42)
unlabeled_data['cluster'] = kmeans.fit_predict(unlabeled_data)
print(unlabeled_data['cluster'].value_counts())
C:\Users\jesse\anaconda3\Lib\site-packages\sklearn\cluster\_kmeans.py:1436: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1. warnings.warn(
cluster 1 40 2 39 0 26 Name: count, dtype: int64
hier voeren we Kmeans op de unlabeled dataset en voegen de clusters toe als kolommen.
unlabeled_cluster = unlabeled_data.groupby('cluster').agg('mean')
display(unlabeled_cluster)
| bandwith | centroid | chromagram10_mean | chromagram11_mean | chromagram12_mean | chromagram1_mean | chromagram2_mean | chromagram3_mean | chromagram4_mean | chromagram5_mean | ... | spectral_contrast7_mean | spectral_flatness | spectral_rolloff | tonnetz1_mean | tonnetz2_mean | tonnetz3_mean | tonnetz4_mean | tonnetz5_mean | tonnetz6_mean | zcr | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| cluster | |||||||||||||||||||||
| 0 | 0.523447 | 0.573262 | 0.556266 | 0.645412 | 0.599113 | 0.648855 | 0.666862 | 0.673735 | 0.685147 | 0.605894 | ... | 0.883251 | 0.153669 | 0.552364 | 0.542640 | 0.341978 | 0.451951 | 0.441608 | 0.395708 | 0.413671 | 0.620927 |
| 1 | 0.234479 | 0.197888 | 0.223155 | 0.361775 | 0.196132 | 0.386166 | 0.210448 | 0.400807 | 0.288687 | 0.200952 | ... | 0.337053 | 0.015374 | 0.197929 | 0.528294 | 0.626156 | 0.484505 | 0.415608 | 0.492764 | 0.430684 | 0.260223 |
| 2 | 0.826579 | 0.747882 | 0.424069 | 0.544913 | 0.483928 | 0.602510 | 0.586091 | 0.560396 | 0.512694 | 0.404926 | ... | 0.067970 | 0.551744 | 0.782709 | 0.530890 | 0.376735 | 0.436866 | 0.419808 | 0.457613 | 0.418868 | 0.610555 |
3 rows × 58 columns
labeled = labeled_df
display(labeled)
| filename | genre | mfcc1_mean | mfcc2_mean | mfcc3_mean | mfcc4_mean | mfcc5_mean | mfcc6_mean | mfcc7_mean | mfcc8_mean | ... | mel_spectral_contrast2_mean | mel_spectral_contrast3_mean | mel_spectral_contrast4_mean | mel_spectral_contrast5_mean | mel_spectral_contrast6_mean | mel_spectral_contrast7_mean | spectral_flatness | zcr | bandwith | centroid | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 8 | m00002.wav | jazz | -298.807953 | 112.078209 | 6.485770 | 28.386517 | -6.764679 | 16.651894 | -11.809684 | 12.746783 | ... | 6.739004 | 17.720329 | 31.856210 | 37.582171 | 36.234603 | 42.188262 | 0.001252 | 0.051222 | 1919.917650 | 1451.498371 |
| 9 | m00039.wav | reggae | -169.243668 | 110.447716 | -8.553957 | 43.898693 | 0.266454 | 26.646509 | -14.365674 | 13.026835 | ... | 8.001072 | 15.869485 | 22.225069 | 29.004593 | 27.931632 | 43.075836 | 0.004306 | 0.072178 | 2019.252686 | 1811.358216 |
| 43 | m00041.wav | pop | -18.854591 | 71.328522 | -3.743232 | -1.396592 | 0.710347 | -1.049137 | -1.052407 | -0.249471 | ... | 5.718698 | 13.057337 | 17.657730 | 23.827369 | 27.071292 | 18.570913 | 0.078506 | 0.152910 | 2992.192112 | 3111.061099 |
| 29 | m00072.wav | disco | -69.599335 | 83.059570 | -16.599524 | 0.119469 | 7.415704 | 0.769619 | 1.337008 | 4.690686 | ... | 6.370224 | 12.197484 | 18.810620 | 25.720595 | 24.686535 | 23.377385 | 0.038270 | 0.120259 | 2709.990169 | 2625.095044 |
| 34 | m00096.wav | disco | -91.886307 | 87.604057 | -2.058175 | 34.285538 | -18.153370 | 19.344702 | -14.697328 | 17.116173 | ... | 4.989545 | 15.582052 | 20.384724 | 25.294628 | 29.771765 | 46.579813 | 0.009796 | 0.115890 | 2486.020650 | 2550.135384 |
| 48 | m00102.wav | classical | -436.842285 | 154.113205 | -19.859337 | 20.183603 | 3.164744 | 0.446392 | -6.530639 | -4.603339 | ... | 8.704671 | 18.088766 | 26.164080 | 36.452103 | 37.462534 | 35.556624 | 0.000976 | 0.066325 | 1517.856160 | 1173.931066 |
| 25 | m00112.wav | reggae | -265.694977 | 80.615921 | 9.722022 | 36.657085 | 27.836796 | 12.086828 | 15.014478 | 15.116937 | ... | 3.927251 | 15.154408 | 20.473471 | 26.257647 | 25.445807 | 24.486615 | 0.026549 | 0.060883 | 2595.217468 | 2113.391953 |
| 4 | m00138.wav | reggae | -198.632797 | 102.413582 | -10.031449 | 30.802383 | -3.310606 | 20.276924 | -5.637373 | 28.095631 | ... | 8.111595 | 11.985461 | 21.690643 | 26.647311 | 26.212014 | 47.129611 | 0.005168 | 0.070323 | 2295.466240 | 1995.600514 |
| 5 | m00192.wav | classical | -85.264992 | 118.423058 | -31.472771 | 20.282015 | -4.417709 | 6.922598 | -10.950942 | -1.620085 | ... | 5.707315 | 9.457773 | 16.339001 | 23.798978 | 26.500622 | 37.537164 | 0.010484 | 0.111613 | 1965.028715 | 1878.774030 |
| 22 | m00206.wav | hiphop | -92.591652 | 77.412682 | -32.756371 | 54.596119 | -13.199195 | 33.656281 | -12.085772 | 28.015388 | ... | 3.856905 | 11.629413 | 12.605242 | 16.697020 | 17.101189 | 52.441041 | 0.018014 | 0.157603 | 2295.456105 | 2735.795802 |
| 1 | m00230.wav | country | -89.736382 | 36.286205 | 11.469535 | 37.495590 | 9.199136 | 3.740519 | 2.840358 | 6.811540 | ... | 4.663522 | 12.311560 | 17.618104 | 28.147029 | 26.801658 | 22.182678 | 0.093471 | 0.212375 | 3053.066772 | 3760.424488 |
| 47 | m00236.wav | classical | -368.465942 | 124.265991 | -31.582445 | 17.601763 | 2.322930 | -5.949597 | -11.807772 | -5.547481 | ... | 4.495887 | 16.020693 | 30.754881 | 34.882406 | 36.114791 | 54.128590 | 0.000620 | 0.078817 | 1415.453381 | 1329.264956 |
| 0 | m00248.wav | metal | -75.517509 | 81.911423 | -22.081079 | 69.876999 | -11.740438 | 25.740246 | -18.518965 | 27.027710 | ... | 2.714730 | 9.285961 | 13.318006 | 15.142012 | 17.020385 | 57.419416 | 0.018547 | 0.158776 | 2337.227557 | 2656.165734 |
| 45 | m00253.wav | blues | -3.559072 | 92.927788 | -25.118544 | 45.187210 | -10.871894 | 31.862423 | -18.057922 | 28.628012 | ... | 3.783532 | 12.969313 | 16.648841 | 21.717000 | 24.115583 | 57.660211 | 0.010716 | 0.124735 | 2358.384492 | 2443.238916 |
| 40 | m00298.wav | blues | -213.204529 | 115.154541 | -11.720503 | 39.032555 | -20.357819 | 13.089926 | -9.180815 | 9.023639 | ... | 5.069766 | 14.647256 | 24.722086 | 30.720819 | 27.451555 | 51.615333 | 0.002710 | 0.079215 | 1973.690309 | 1817.529547 |
| 27 | m00313.wav | blues | -249.289398 | 130.987030 | 0.677390 | 66.685783 | 17.897806 | 4.623737 | 6.598308 | 1.249050 | ... | 4.712652 | 16.387888 | 25.459972 | 31.543672 | 29.853833 | 51.528179 | 0.000401 | 0.051725 | 1463.539070 | 1109.721379 |
| 39 | m00338.wav | blues | -55.596630 | 114.951218 | -37.069351 | 64.904381 | -7.164943 | 15.254702 | -16.235331 | 18.643576 | ... | 3.855680 | 11.104764 | 19.421730 | 24.030727 | 23.153801 | 59.228233 | 0.004599 | 0.106627 | 1927.439014 | 1977.108904 |
| 44 | m00339.wav | rock | -70.117538 | 94.181656 | -50.328033 | 46.962898 | -16.114254 | 19.996185 | -23.959724 | 16.344028 | ... | 3.767756 | 8.777708 | 17.115519 | 22.762585 | 21.009458 | 66.166621 | 0.014635 | 0.150945 | 2102.197363 | 2471.302264 |
| 32 | m00351.wav | jazz | -192.517395 | 113.183693 | -6.373058 | 39.593094 | -9.189579 | 17.204056 | -19.114599 | 12.203582 | ... | 4.895479 | 13.100308 | 18.168636 | 31.750680 | 30.777813 | 52.074700 | 0.003388 | 0.076921 | 2107.923976 | 1825.975175 |
| 16 | m00400.wav | blues | -350.358887 | 169.546326 | 31.780231 | 16.713755 | 28.661758 | 19.249090 | 7.846700 | 10.039796 | ... | 6.831016 | 15.706191 | 25.741073 | 31.403125 | 30.358803 | 22.970648 | 0.000457 | 0.021701 | 995.093473 | 570.150688 |
| 13 | m00421.wav | pop | -77.941887 | 32.364956 | 20.077257 | 27.633484 | 16.262774 | 5.319164 | 13.481539 | 3.503227 | ... | 9.366871 | 17.067590 | 22.242897 | 24.953492 | 25.764494 | 21.049781 | 0.066714 | 0.144787 | 3223.867461 | 3727.248835 |
| 6 | m00429.wav | hiphop | -109.509178 | 97.389557 | -20.619621 | 37.366669 | -3.125998 | 28.611204 | -14.169424 | 23.862110 | ... | 4.376860 | 8.659314 | 15.042835 | 21.151530 | 22.051505 | 50.071179 | 0.011507 | 0.104502 | 2327.237804 | 2272.834439 |
| 46 | m00435.wav | classical | -207.377472 | 117.607780 | -41.404255 | 13.253087 | -1.688240 | 15.532319 | -10.362769 | -1.863690 | ... | 4.804461 | 20.265242 | 22.574447 | 30.592474 | 40.035231 | 56.377036 | 0.000801 | 0.108258 | 1551.481235 | 1623.829998 |
| 35 | m00454.wav | hiphop | -103.138268 | 74.090218 | -22.434641 | 51.604790 | -7.079813 | 32.670975 | -14.993524 | 19.642502 | ... | 5.691232 | 11.065545 | 15.903900 | 23.839271 | 22.870837 | 53.006697 | 0.016491 | 0.117624 | 2396.648334 | 2670.154564 |
| 49 | m00477.wav | classical | -412.959259 | 138.519836 | -19.262381 | 34.146679 | 8.975063 | -4.294471 | 4.152584 | 0.881950 | ... | 5.582785 | 20.293131 | 30.609275 | 42.342264 | 38.614245 | 38.829502 | 0.000672 | 0.060885 | 1467.205561 | 1171.844481 |
| 14 | m00501.wav | jazz | -168.123230 | 108.271530 | -14.149940 | 30.457626 | 3.894506 | 4.676564 | 3.187918 | 1.927635 | ... | 5.479137 | 19.986478 | 27.292205 | 31.991843 | 30.909894 | 30.390149 | 0.006512 | 0.067522 | 2091.113741 | 1725.634530 |
| 12 | m00503.wav | metal | -93.591331 | 89.894020 | -55.902695 | 51.637325 | -5.558396 | 28.777815 | -13.892873 | 27.350773 | ... | 6.208451 | 8.601995 | 15.799067 | 22.311950 | 21.688064 | 62.071454 | 0.012679 | 0.151809 | 2037.300179 | 2463.449458 |
| 42 | m00513.wav | pop | -52.649151 | 47.782742 | 13.455156 | 2.213427 | 13.251046 | 9.133875 | 14.447654 | 0.873837 | ... | 7.743124 | 10.976887 | 14.634204 | 21.740248 | 26.191926 | 20.857168 | 0.097539 | 0.210715 | 3426.219520 | 4052.888670 |
| 36 | m00553.wav | disco | -95.103706 | 109.353172 | -30.161179 | 16.358656 | 20.039730 | 11.962816 | 3.485530 | 6.173969 | ... | 4.868121 | 11.508925 | 16.536470 | 23.614719 | 23.721108 | 29.510298 | 0.026017 | 0.103663 | 2143.899287 | 2117.550762 |
| 33 | m00606.wav | country | -171.339005 | 137.354568 | 7.964579 | 28.539564 | 2.708197 | -0.501510 | -2.956100 | -1.159342 | ... | 6.591413 | 10.533838 | 16.756754 | 25.936614 | 26.975167 | 28.856986 | 0.007312 | 0.063856 | 1959.987665 | 1469.784950 |
| 7 | m00623.wav | reggae | -94.140526 | 68.229942 | 3.975480 | 7.631387 | 12.791034 | -3.185735 | -3.907444 | 3.817600 | ... | 7.047003 | 16.691960 | 18.115008 | 23.019129 | 24.171044 | 21.322361 | 0.065537 | 0.136075 | 2974.065401 | 3086.186001 |
| 3 | m00627.wav | metal | -57.683388 | 101.432327 | -41.485245 | 55.130600 | -23.349279 | 28.151102 | -12.139105 | 18.150204 | ... | 4.042038 | 9.291089 | 13.214748 | 17.212025 | 17.637471 | 58.275039 | 0.012321 | 0.141317 | 2092.439557 | 2378.392048 |
| 17 | m00629.wav | country | -82.962616 | 122.532806 | -16.658556 | 40.015911 | -15.007229 | 21.670378 | -18.256283 | 18.361864 | ... | 5.854305 | 15.034976 | 18.742446 | 24.931771 | 25.955064 | 54.375683 | 0.005227 | 0.081104 | 2116.237657 | 1881.161818 |
| 28 | m00633.wav | country | -122.427414 | 111.483139 | -13.694294 | 53.828403 | -2.677765 | 19.677549 | -14.138923 | 13.743676 | ... | 5.908667 | 12.477974 | 21.097610 | 27.547413 | 27.157049 | 52.619927 | 0.005293 | 0.078317 | 2085.606346 | 1879.937791 |
| 2 | m00637.wav | hiphop | -122.780525 | 95.061287 | -29.363251 | 46.780045 | -15.998561 | 27.117586 | -13.113779 | 20.258003 | ... | 6.453961 | 10.992537 | 16.350120 | 21.788517 | 20.466351 | 50.293757 | 0.013041 | 0.113229 | 2181.589027 | 2290.107318 |
| 38 | m00658.wav | hiphop | -105.569511 | 76.674911 | -24.774305 | 55.198990 | -8.257657 | 28.899265 | -15.747581 | 26.304575 | ... | 3.862585 | 12.135674 | 13.885980 | 19.403479 | 20.607843 | 53.621895 | 0.013526 | 0.138555 | 2350.956242 | 2628.976734 |
| 21 | m00671.wav | reggae | -251.392563 | 105.855774 | 2.220024 | 32.484390 | 16.563274 | 8.290815 | 10.365557 | 5.504937 | ... | 6.202627 | 13.453879 | 14.213644 | 19.654592 | 19.496502 | 29.640906 | 0.026613 | 0.089780 | 2298.145722 | 2004.353847 |
| 23 | m00676.wav | pop | 9.675074 | 88.826073 | -20.293680 | 5.101305 | -2.917802 | -0.188181 | 0.327482 | 1.604321 | ... | 3.538988 | 9.555049 | 13.832719 | 17.227212 | 19.715628 | 21.549278 | 0.064364 | 0.131656 | 2559.529362 | 2569.255823 |
| 10 | m00677.wav | country | -139.623062 | 128.793533 | -20.249359 | 49.443615 | -2.160360 | 16.988024 | -8.355296 | 9.818295 | ... | 7.767790 | 18.787435 | 27.903697 | 35.160599 | 34.218542 | 48.088884 | 0.001416 | 0.061745 | 1690.685707 | 1425.263509 |
| 20 | m00678.wav | metal | -95.339104 | 92.066360 | -28.061176 | 52.796284 | -3.018975 | 25.395771 | -6.135991 | 20.098093 | ... | 3.902639 | 12.254983 | 15.608343 | 18.157071 | 18.915123 | 47.654008 | 0.011364 | 0.115765 | 2115.725580 | 2241.454932 |
| 31 | m00716.wav | jazz | -202.608383 | 105.845734 | -20.537838 | 43.897964 | -14.272349 | 25.299541 | -15.592009 | 15.311663 | ... | 5.576754 | 14.930754 | 16.889706 | 26.349590 | 28.195721 | 51.507869 | 0.006012 | 0.093247 | 2084.706315 | 2034.579158 |
| 18 | m00762.wav | disco | -155.637314 | 60.568497 | 23.166864 | 31.186348 | 25.054384 | 16.906994 | 9.438360 | 8.449133 | ... | 4.454963 | 14.698277 | 18.425711 | 22.050855 | 20.513930 | 20.602898 | 0.045092 | 0.101249 | 2990.754025 | 2909.983968 |
| 37 | m00772.wav | rock | -125.065109 | 115.203308 | -48.004681 | 52.843102 | -13.491938 | 21.765408 | -12.428561 | 20.139965 | ... | 5.201100 | 10.631122 | 18.387787 | 22.359313 | 22.331249 | 61.219149 | 0.007513 | 0.121824 | 1926.895810 | 2077.166788 |
| 26 | m00773.wav | pop | -204.752975 | 101.605118 | 26.384224 | 9.185719 | 10.460928 | 5.108919 | -9.447198 | 9.308316 | ... | 9.920602 | 17.031494 | 27.189178 | 34.895090 | 35.677321 | 28.118941 | 0.009270 | 0.075366 | 2559.593931 | 2053.894372 |
| 15 | m00801.wav | rock | -212.298355 | 65.759850 | 45.182362 | 19.730082 | 11.805884 | 8.061574 | 4.434145 | 4.215858 | ... | 7.496245 | 14.080840 | 24.372299 | 29.930723 | 29.264457 | 19.750201 | 0.031043 | 0.108570 | 3203.015264 | 2947.109224 |
| 24 | m00821.wav | metal | -58.720360 | 70.558182 | -19.421354 | 73.593155 | -27.765425 | 23.759441 | -17.904169 | 21.222898 | ... | 3.810858 | 9.925774 | 14.813298 | 17.154393 | 16.498257 | 62.176253 | 0.025555 | 0.196540 | 2358.882414 | 3048.505206 |
| 41 | m00850.wav | disco | -78.351181 | 80.074615 | -9.167377 | 25.477053 | -3.390544 | 16.809401 | 7.270706 | 1.818662 | ... | 3.839945 | 11.835582 | 16.459640 | 24.339468 | 26.110460 | 26.963877 | 0.040865 | 0.126389 | 2533.400412 | 2605.158779 |
| 11 | m00867.wav | rock | -142.442062 | 116.238441 | -32.190319 | 49.114605 | -8.395415 | 22.872288 | -18.311134 | 20.106487 | ... | 7.675207 | 11.516393 | 18.302119 | 25.070244 | 23.581773 | 56.706450 | 0.006455 | 0.097659 | 2068.224879 | 2006.009248 |
| 19 | m00895.wav | rock | -26.406458 | 85.794289 | -16.961445 | 35.260883 | 10.000134 | 10.668921 | 1.446997 | 4.710635 | ... | 4.893592 | 13.844285 | 19.658359 | 25.195343 | 25.510141 | 32.623636 | 0.027207 | 0.115493 | 2378.385172 | 2345.885737 |
| 30 | m00996.wav | jazz | -235.678848 | 144.767654 | -22.600695 | 62.560963 | -9.326273 | 2.016869 | -0.343650 | 2.016511 | ... | 4.571889 | 12.846922 | 19.813868 | 31.435092 | 32.057657 | 49.188174 | 0.001253 | 0.076529 | 1518.994776 | 1338.236233 |
50 rows × 60 columns
label_scaled = scaler(labeled)
label_scaled['genre'] = labeled['genre']
label_scaled = label_scaled.groupby('genre').agg('mean', numeric_only=True)
# Drop 'index' en 'sfreq' kolommen
display(label_scaled)
| bandwith | centroid | chromagram10_mean | chromagram11_mean | chromagram12_mean | chromagram1_mean | chromagram2_mean | chromagram3_mean | chromagram4_mean | chromagram5_mean | ... | spectral_contrast7_mean | spectral_flatness | spectral_rolloff | tonnetz1_mean | tonnetz2_mean | tonnetz3_mean | tonnetz4_mean | tonnetz5_mean | tonnetz6_mean | zcr | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| genre | |||||||||||||||||||||
| blues | 0.570724 | 0.603191 | 0.568935 | 0.512389 | 0.612034 | 0.713023 | 0.611799 | 0.789955 | 0.630810 | 0.617932 | ... | 0.696037 | 0.294558 | 0.595083 | 0.373805 | 0.533733 | 0.794573 | 0.513532 | 0.688573 | 0.437988 | 0.644441 |
| classical | 0.414737 | 0.380073 | 0.462212 | 0.307737 | 0.345461 | 0.437768 | 0.432761 | 0.529028 | 0.379019 | 0.562687 | ... | 0.221291 | 0.153904 | 0.387208 | 0.551137 | 0.488247 | 0.597860 | 0.573020 | 0.710912 | 0.470433 | 0.392179 |
| country | 0.528854 | 0.527735 | 0.502125 | 0.568212 | 0.442093 | 0.674517 | 0.573105 | 0.680076 | 0.633341 | 0.541148 | ... | 0.520322 | 0.291785 | 0.525166 | 0.222558 | 0.655681 | 0.693533 | 0.498192 | 0.733933 | 0.488153 | 0.533868 |
| disco | 0.539909 | 0.439278 | 0.620382 | 0.531246 | 0.503473 | 0.582386 | 0.525130 | 0.789353 | 0.553296 | 0.569495 | ... | 0.372165 | 0.192389 | 0.474003 | 0.454328 | 0.598727 | 0.728963 | 0.396498 | 0.617229 | 0.441749 | 0.352991 |
| hiphop | 0.510468 | 0.462382 | 0.379884 | 0.378835 | 0.367477 | 0.552595 | 0.435395 | 0.474046 | 0.386888 | 0.513529 | ... | 0.488845 | 0.244584 | 0.483315 | 0.347749 | 0.602565 | 0.637329 | 0.524570 | 0.590138 | 0.504995 | 0.434090 |
| jazz | 0.505609 | 0.470394 | 0.487221 | 0.416552 | 0.386641 | 0.413832 | 0.499157 | 0.746797 | 0.564836 | 0.518794 | ... | 0.543609 | 0.194101 | 0.492837 | 0.363454 | 0.562417 | 0.721323 | 0.449418 | 0.583019 | 0.335821 | 0.462383 |
| metal | 0.549765 | 0.504264 | 0.439388 | 0.459322 | 0.412351 | 0.556741 | 0.431805 | 0.456267 | 0.461138 | 0.397431 | ... | 0.342797 | 0.254174 | 0.515288 | 0.221448 | 0.647024 | 0.680236 | 0.644194 | 0.529290 | 0.368040 | 0.448331 |
| pop | 0.518554 | 0.508631 | 0.570681 | 0.543371 | 0.445909 | 0.539751 | 0.522993 | 0.705792 | 0.605422 | 0.568796 | ... | 0.738439 | 0.112546 | 0.516186 | 0.328336 | 0.630846 | 0.700289 | 0.446648 | 0.649486 | 0.415466 | 0.506472 |
| reggae | 0.536363 | 0.484059 | 0.481324 | 0.469088 | 0.555118 | 0.779702 | 0.515746 | 0.643189 | 0.522847 | 0.576208 | ... | 0.718651 | 0.100871 | 0.520251 | 0.323629 | 0.584332 | 0.674909 | 0.578131 | 0.577892 | 0.368364 | 0.427260 |
| rock | 0.383457 | 0.325879 | 0.421623 | 0.541028 | 0.499974 | 0.520385 | 0.349906 | 0.496622 | 0.391111 | 0.428603 | ... | 0.291130 | 0.195351 | 0.357569 | 0.407569 | 0.446922 | 0.680467 | 0.528873 | 0.732854 | 0.241475 | 0.297855 |
10 rows × 58 columns
def bereken_afstanden(genre_data, cluster_data):
afstanden = []
for genre_row in genre_data.iterrows():
genre_name, genre_values = genre_row
for cluster_row in cluster_data.iterrows():
cluster_name, cluster_values = cluster_row
distance = euclidean(genre_values, cluster_values)
afstanden.append((genre_name, cluster_name, distance))
return afstanden
afstanden = bereken_afstanden(label_scaled, unlabeled_cluster)
for genre_name, cluster_name, distance in afstanden:
print(f"Afstand tussen {genre_name} en {cluster_name}: {distance}")
Afstand tussen blues en 0: 1.0170016124005132 Afstand tussen blues en 1: 2.1937363809353783 Afstand tussen blues en 2: 1.6445935562510356 Afstand tussen classical en 0: 2.115576584984316 Afstand tussen classical en 1: 1.126995881284671 Afstand tussen classical en 2: 1.5609093560555085 Afstand tussen country en 0: 1.5208883988424096 Afstand tussen country en 1: 1.7308268295016342 Afstand tussen country en 2: 1.515958030022638 Afstand tussen disco en 0: 1.6991841237131824 Afstand tussen disco en 1: 1.6767710966838931 Afstand tussen disco en 2: 1.3301505499765294 Afstand tussen hiphop en 0: 1.8854796656682073 Afstand tussen hiphop en 1: 1.2754201227992885 Afstand tussen hiphop en 2: 1.3846956845653426 Afstand tussen jazz en 0: 1.5660622016899195 Afstand tussen jazz en 1: 1.5318736189929327 Afstand tussen jazz en 2: 1.5465033832284947 Afstand tussen metal en 0: 2.1148332404711585 Afstand tussen metal en 1: 1.3690411500947441 Afstand tussen metal en 2: 1.397694757640086 Afstand tussen pop en 0: 1.122777838548499 Afstand tussen pop en 1: 1.930676190840679 Afstand tussen pop en 2: 1.8921279690022645 Afstand tussen reggae en 0: 1.1997686898611621 Afstand tussen reggae en 1: 1.8317876893179585 Afstand tussen reggae en 2: 1.7026037585260427 Afstand tussen rock en 0: 2.543455097958965 Afstand tussen rock en 1: 1.1754147711176846 Afstand tussen rock en 2: 1.6097773260146777
def bereken_manhattan_afstanden(genre_data, cluster_data):
afstanden = []
for genre_row in genre_data.iterrows():
genre_name, genre_values = genre_row
for cluster_row in cluster_data.iterrows():
cluster_name, cluster_values = cluster_row
distance = cityblock(genre_values, cluster_values)
afstanden.append((genre_name, cluster_name, distance))
return afstanden
manhattan_afstanden = bereken_manhattan_afstanden(label_scaled, unlabeled_cluster)
for genre_name, cluster_name, distance in manhattan_afstanden:
print(f"Manhattan-afstand tussen {genre_name} en {cluster_name}: {distance}")
Manhattan-afstand tussen blues en 0: 6.197687605947785 Manhattan-afstand tussen blues en 1: 15.136279347730634 Manhattan-afstand tussen blues en 2: 10.064613083168368 Manhattan-afstand tussen classical en 0: 14.35685898646447 Manhattan-afstand tussen classical en 1: 7.48821444770054 Manhattan-afstand tussen classical en 2: 10.219852674924203 Manhattan-afstand tussen country en 0: 10.048769422698081 Manhattan-afstand tussen country en 1: 11.661693646645618 Manhattan-afstand tussen country en 2: 9.742798586207428 Manhattan-afstand tussen disco en 0: 10.99529378631154 Manhattan-afstand tussen disco en 1: 11.014624300158 Manhattan-afstand tussen disco en 2: 8.166065040840166 Manhattan-afstand tussen hiphop en 0: 12.619247319530173 Manhattan-afstand tussen hiphop en 1: 8.459395800905478 Manhattan-afstand tussen hiphop en 2: 8.692641531239193 Manhattan-afstand tussen jazz en 0: 10.339367587900833 Manhattan-afstand tussen jazz en 1: 10.07530220380237 Manhattan-afstand tussen jazz en 2: 9.523560213474553 Manhattan-afstand tussen metal en 0: 14.155633807717635 Manhattan-afstand tussen metal en 1: 8.725749618872847 Manhattan-afstand tussen metal en 2: 9.158480113059607 Manhattan-afstand tussen pop en 0: 7.122335811350672 Manhattan-afstand tussen pop en 1: 13.206176449965824 Manhattan-afstand tussen pop en 2: 11.444614980868499 Manhattan-afstand tussen reggae en 0: 7.984582411817846 Manhattan-afstand tussen reggae en 1: 12.339350610407957 Manhattan-afstand tussen reggae en 2: 10.42148998666098 Manhattan-afstand tussen rock en 0: 17.266382795487495 Manhattan-afstand tussen rock en 1: 7.546078980257016 Manhattan-afstand tussen rock en 2: 10.13951647202089
def bepaal_genres_voor_clusters(genre_data, cluster_data, afstanden_functie):
toewijzingen = []
for cluster_row in cluster_data.iterrows():
cluster_name, cluster_values = cluster_row
min_afstand = float('inf')
op_een_na_min_afstand = float('inf')
toegewezen_genre = None
op_een_na_toegewezen_genre = None
for genre_row in genre_data.iterrows():
genre_name, genre_values = genre_row
afstand = afstanden_functie(genre_values, cluster_values)
if afstand < min_afstand:
op_een_na_min_afstand = min_afstand
op_een_na_toegewezen_genre = toegewezen_genre
min_afstand = afstand
toegewezen_genre = genre_name
elif afstand < op_een_na_min_afstand:
op_een_na_min_afstand = afstand
op_een_na_toegewezen_genre = genre_name
toewijzingen.append((cluster_name, toegewezen_genre, min_afstand, op_een_na_toegewezen_genre, op_een_na_min_afstand))
return toewijzingen
toewijzingen_euclidisch = bepaal_genres_voor_clusters(label_scaled, unlabeled_cluster, euclidean)
toewijzingen_manhattan = bepaal_genres_voor_clusters(label_scaled, unlabeled_cluster, cityblock)
print("Toewijzingen op basis van Euclidische afstanden:")
for cluster_name, genre_name, afstand, op_een_na_genre, op_een_na_afstand in toewijzingen_euclidisch:
print(f"Cluster {cluster_name} is toegewezen aan genre {genre_name} met een afstand {afstand}. Op één na dichtstbijzijnde genre: {op_een_na_genre} met een afstand {op_een_na_afstand}")
print("\nToewijzingen op basis van Manhattan-afstanden:")
for cluster_name, genre_name, afstand, op_een_na_genre, op_een_na_afstand in toewijzingen_manhattan:
print(f"Cluster {cluster_name} is toegewezen aan genre {genre_name} met een afstand {afstand}. Op één na dichtstbijzijnde genre: {op_een_na_genre} met een afstand {op_een_na_afstand}")
Toewijzingen op basis van Euclidische afstanden: Cluster 0 is toegewezen aan genre blues met een afstand 1.0170016124005132. Op één na dichtstbijzijnde genre: pop met een afstand 1.122777838548499 Cluster 1 is toegewezen aan genre classical met een afstand 1.126995881284671. Op één na dichtstbijzijnde genre: rock met een afstand 1.1754147711176846 Cluster 2 is toegewezen aan genre disco met een afstand 1.3301505499765294. Op één na dichtstbijzijnde genre: hiphop met een afstand 1.3846956845653426 Toewijzingen op basis van Manhattan-afstanden: Cluster 0 is toegewezen aan genre blues met een afstand 6.197687605947785. Op één na dichtstbijzijnde genre: pop met een afstand 7.122335811350672 Cluster 1 is toegewezen aan genre classical met een afstand 7.48821444770054. Op één na dichtstbijzijnde genre: rock met een afstand 7.546078980257016 Cluster 2 is toegewezen aan genre disco met een afstand 8.166065040840166. Op één na dichtstbijzijnde genre: hiphop met een afstand 8.692641531239193
def plot_vis(data1, data2, x, y):
plt.figure(figsize=(15, 6))
sns.scatterplot(data=data1,
x=x,
y=y,
hue='cluster',
palette='viridis',
marker='o',
legend='full')
sns.scatterplot(data=data2,
x=x,
y=y,
hue='genre',
marker='D',
legend='full')
plt.title(f'Scatter Plot van {x} en {y} met Cluster- en Genrevergelijking')
plt.xlabel(x)
plt.ylabel(y)
plt.legend(loc='upper right')
plt.grid(True)
plt.show()
unlabeled_cluster.reset_index(inplace=True)
display(unlabeled_cluster.head())
label_scaled.reset_index(inplace=True)
display(label_scaled.head())
| cluster | bandwith | centroid | chromagram10_mean | chromagram11_mean | chromagram12_mean | chromagram1_mean | chromagram2_mean | chromagram3_mean | chromagram4_mean | ... | spectral_contrast7_mean | spectral_flatness | spectral_rolloff | tonnetz1_mean | tonnetz2_mean | tonnetz3_mean | tonnetz4_mean | tonnetz5_mean | tonnetz6_mean | zcr | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 0.523447 | 0.573262 | 0.556266 | 0.645412 | 0.599113 | 0.648855 | 0.666862 | 0.673735 | 0.685147 | ... | 0.883251 | 0.153669 | 0.552364 | 0.542640 | 0.341978 | 0.451951 | 0.441608 | 0.395708 | 0.413671 | 0.620927 |
| 1 | 1 | 0.234479 | 0.197888 | 0.223155 | 0.361775 | 0.196132 | 0.386166 | 0.210448 | 0.400807 | 0.288687 | ... | 0.337053 | 0.015374 | 0.197929 | 0.528294 | 0.626156 | 0.484505 | 0.415608 | 0.492764 | 0.430684 | 0.260223 |
| 2 | 2 | 0.826579 | 0.747882 | 0.424069 | 0.544913 | 0.483928 | 0.602510 | 0.586091 | 0.560396 | 0.512694 | ... | 0.067970 | 0.551744 | 0.782709 | 0.530890 | 0.376735 | 0.436866 | 0.419808 | 0.457613 | 0.418868 | 0.610555 |
3 rows × 59 columns
| genre | bandwith | centroid | chromagram10_mean | chromagram11_mean | chromagram12_mean | chromagram1_mean | chromagram2_mean | chromagram3_mean | chromagram4_mean | ... | spectral_contrast7_mean | spectral_flatness | spectral_rolloff | tonnetz1_mean | tonnetz2_mean | tonnetz3_mean | tonnetz4_mean | tonnetz5_mean | tonnetz6_mean | zcr | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | blues | 0.570724 | 0.603191 | 0.568935 | 0.512389 | 0.612034 | 0.713023 | 0.611799 | 0.789955 | 0.630810 | ... | 0.696037 | 0.294558 | 0.595083 | 0.373805 | 0.533733 | 0.794573 | 0.513532 | 0.688573 | 0.437988 | 0.644441 |
| 1 | classical | 0.414737 | 0.380073 | 0.462212 | 0.307737 | 0.345461 | 0.437768 | 0.432761 | 0.529028 | 0.379019 | ... | 0.221291 | 0.153904 | 0.387208 | 0.551137 | 0.488247 | 0.597860 | 0.573020 | 0.710912 | 0.470433 | 0.392179 |
| 2 | country | 0.528854 | 0.527735 | 0.502125 | 0.568212 | 0.442093 | 0.674517 | 0.573105 | 0.680076 | 0.633341 | ... | 0.520322 | 0.291785 | 0.525166 | 0.222558 | 0.655681 | 0.693533 | 0.498192 | 0.733933 | 0.488153 | 0.533868 |
| 3 | disco | 0.539909 | 0.439278 | 0.620382 | 0.531246 | 0.503473 | 0.582386 | 0.525130 | 0.789353 | 0.553296 | ... | 0.372165 | 0.192389 | 0.474003 | 0.454328 | 0.598727 | 0.728963 | 0.396498 | 0.617229 | 0.441749 | 0.352991 |
| 4 | hiphop | 0.510468 | 0.462382 | 0.379884 | 0.378835 | 0.367477 | 0.552595 | 0.435395 | 0.474046 | 0.386888 | ... | 0.488845 | 0.244584 | 0.483315 | 0.347749 | 0.602565 | 0.637329 | 0.524570 | 0.590138 | 0.504995 | 0.434090 |
5 rows × 59 columns
clusters = [0]
genres = ['disco', 'pop']
x = 'rms_energy'
y = 'mfcc11_mean'
plot_vis(
data1=unlabeled_data[unlabeled_data['cluster'].isin(clusters)],
data2=label_scaled[label_scaled['genre'].isin(genres)],
x=x,
y=y
)
clusters = [1]
genres = ['metal', 'hiphop']
plot_vis(
data1=unlabeled_data[unlabeled_data['cluster'].isin(clusters)],
data2=label_scaled[label_scaled['genre'].isin(genres)],
x=x,
y=y
)
clusters = [2]
genres = ['jazz', 'classical']
x = 'rms_energy'
y = 'mfcc11_mean'
plot_vis(
data1=unlabeled_data[unlabeled_data['cluster'].isin(clusters)],
data2=label_scaled[label_scaled['genre'].isin(genres)],
x=x,
y=y
)
Om een voorbeeld te geven van het uitvoeren van PCA hebben we eerst een dataset nodig. Voor het gemak maken wij gebruik van een kleine zelf verzonnen dataset. | | X1 | X2 | |-------|:-----:|:-----:| | 1 | 4 | 1 | | 2 | 2 | 3 | | 3 | 7 | 6 | | 4 | 5 | 4 | | 5 | 9 | 8 |
De eerste stap voor het uitvoeren van PCA is het standaardiseren van de bovenstaande dataset. Dit doen wij aan de hand van de formule voor de Z-score. $$ Z = \frac{{X - \mu}}{{\sigma}} $$
Door het toepassen van de Z-score krijgen wij de volgende gestandaardiseerde dataset:
| xz1 | xz2 | |
|---|---|---|
| 1 | -0.6325 | -1.2649 |
| 2 | -1.2649 | 0 |
| 3 | 0.6325 | 0.6325 |
| 4 | 0 | -0.6325 |
| 5 | 1.8974 | 1.2649 |
Vervolgen bereken wij de covariantie matrix van de gestandaardiseerde dataset. Dit doen wij aan de hand van de volgende formule:
$$ Cov(X_i, X_j) = \frac{\sum_{k=1}^{n}(X_i^k - \bar{X_i})(X_j^k - \bar{X_j})}{n-1} $$Wanneer wij de bovenstaande formule toepassen krijgen wij het volgende matrix:
\begin{bmatrix} 6.75 & 0.5 \\ 0.5 & 5.0 \end{bmatrix}In stap 3 berekenen wij de eigenwaarden en eigenvectoren.
Eigenwaarden: \begin{align*} \lambda_1 &= 1.9 \\ \lambda_2 &= 0.8 \end{align*}
Eigenvectoren: \begin{align*} v_1 &= \begin{bmatrix} 0.84 \\ 0.54 \end{bmatrix} \quad (\text{bij } \lambda_1) \\ v_2 &= \begin{bmatrix} -0.54 \\ 0.84 \end{bmatrix} \quad (\text{bij } \lambda_2) \end{align*}
Wanneer we kijken naar stap 3 zien we dat vector 1 de meeste significantie heeft, dit is dus de vector met de hoogste eigenwaarde. We selecteren daarom v1 als ons eerst principal component. v_1 &= \begin{bmatrix} 0.84 \\ 0.54 \end{bmatrix}
Voor stap 5 gaan we de gestandaardiseerde gegevens vermenigvuldigen met de gekozen feature vector. Vervolgens krijgen de nieuwe dataset: $$[-0.6325, -1.2649, -1.2649, 0.6325, 0.6325] \cdot [0.84, 0.54] = [-1.6326, -1.2649, -0.0810, 2.6305] $$ Zo komen wij tot een nieuwe dataset die is gereduceerd tot één dimensie, de eerste principale component.
| Nieuwe Dataset | |
|---|---|
| 1 | -1.6326 |
| 2 | -1.2649 |
| 3 | -0.0810 |
| 4 | 2.6305 |
Voor het uitvoeren van een simpele PCA hebben wij de stappen gevolgd die beschreven staan in het volgende artikel. (Jaadi, 2023)
Nu dat wij een voorbeeld hebben gegeven van een simpele principal componenent analyse gaan wij dit nu uitvoeren op onze eigen dataset.
# Stap 1: Standaardiseren
#De data is eerder al gestandaardiseerd. Deze data kunnen we hier hergebruiken
scaled_df = data
# Stap 2: Covariantiematrix
# We maken een covariantiematrix aan de hand van no.cov
cov_matrix = np.cov(scaled_df, rowvar=False)
# Stap 3: Eigenwaarden en Eigenvectoren
eigenvalues, eigenvectors = np.linalg.eig(cov_matrix)
# Nu sorteren wij de waardes
sorted_indices = np.argsort(eigenvalues)[::-1]
eigenvalues = eigenvalues[sorted_indices]
eigenvectors = eigenvectors[:, sorted_indices]
# Aantal principal compponents kiezen
plt.plot(eigenvalues, marker='o')
plt.xlabel('Index')
plt.ylabel('Eigenvalue')
plt.title('Eigenvalues voor het bepalen van het aantal principal components')
plt.show()
# Stap 4: Feature vector
pca_num = 3
principal_components = eigenvectors[:, -pca_num:]
# Stap 5: Projectie
pca = PCA(n_components=pca_num)
data_pca = pca.fit_transform(scaled_df)
# Resultaten toevoegen aan dataframe
unlabeld_new = unlabeled_data.copy()
for i in range(pca_num):
unlabeld_new[f'PC{i+1}'] = data_pca[:, i]
# Toon het resultaat
display(unlabeled_data.head())
| bandwith | centroid | chromagram10_mean | chromagram11_mean | chromagram12_mean | chromagram1_mean | chromagram2_mean | chromagram3_mean | chromagram4_mean | chromagram5_mean | ... | spectral_flatness | spectral_rolloff | tonnetz1_mean | tonnetz2_mean | tonnetz3_mean | tonnetz4_mean | tonnetz5_mean | tonnetz6_mean | zcr | cluster | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0.448700 | 0.463313 | 0.536488 | 0.723331 | 0.959317 | 0.760275 | 0.628028 | 0.688307 | 0.598168 | 0.561027 | ... | 0.075079 | 0.446538 | 0.601636 | 0.327193 | 0.433945 | 0.462291 | 0.286771 | 0.359017 | 0.485893 | 0 |
| 1 | 0.531218 | 0.660143 | 0.431423 | 0.385958 | 0.370729 | 0.728339 | 0.920078 | 0.984592 | 0.734350 | 0.421036 | ... | 0.220823 | 0.583361 | 0.565916 | 0.462638 | 0.419674 | 0.263680 | 0.141557 | 0.452145 | 0.803681 | 0 |
| 2 | 0.370122 | 0.372563 | 0.584292 | 0.383882 | 0.094401 | 0.600906 | 0.101713 | 0.107339 | 0.045195 | 0.394422 | ... | 0.017305 | 0.366321 | 0.539972 | 0.673517 | 0.074136 | 0.513645 | 0.213762 | 0.537025 | 0.504171 | 1 |
| 3 | 0.449617 | 0.502558 | 0.360861 | 0.606008 | 0.721541 | 0.650086 | 0.515102 | 0.610834 | 0.835636 | 1.000000 | ... | 0.073118 | 0.473765 | 0.552052 | 0.282639 | 0.611838 | 0.573084 | 0.650816 | 0.246407 | 0.518485 | 0 |
| 4 | 0.000000 | 0.022579 | 0.115212 | 0.573531 | 0.077500 | 0.000000 | 0.021968 | 0.402056 | 0.456909 | 0.020207 | ... | 0.000000 | 0.016254 | 0.234122 | 0.581224 | 0.558948 | 0.000000 | 0.204898 | 0.412068 | 0.112807 | 1 |
5 rows × 59 columns
#PCA toevoegen aan dataset
df_pca = scaled_df.copy()
for i in range(pca_num):
df_pca[f'PC{i+1}'] = data_pca[:, i]
pca_df = df_pca[['PC1', 'PC2', 'PC3']]
#Getransformeerde dataset
display(pca_df.head())
| PC1 | PC2 | PC3 | |
|---|---|---|---|
| 0 | 1.836866 | -0.018816 | 0.010516 |
| 1 | 1.996875 | 0.314686 | 0.013659 |
| 2 | 0.181995 | -1.041242 | 1.209566 |
| 3 | 1.909274 | 0.041188 | -0.277533 |
| 4 | -0.783876 | -1.630182 | -0.864740 |
display(pca_df)
| PC1 | PC2 | PC3 | |
|---|---|---|---|
| 0 | 1.836866 | -0.018816 | 0.010516 |
| 1 | 1.996875 | 0.314686 | 0.013659 |
| 2 | 0.181995 | -1.041242 | 1.209566 |
| 3 | 1.909274 | 0.041188 | -0.277533 |
| 4 | -0.783876 | -1.630182 | -0.864740 |
| ... | ... | ... | ... |
| 100 | -0.326987 | -0.804086 | -0.660464 |
| 101 | -0.827754 | 1.464652 | -0.120512 |
| 102 | -0.867682 | 1.468914 | 0.062264 |
| 103 | -0.416413 | -1.447649 | 0.040551 |
| 104 | -0.105994 | -1.337032 | -0.439203 |
105 rows × 3 columns
scaler = MinMaxScaler()
columns_to_scale = unlabeled_df.columns[1:]
scaled_data = scaler.fit_transform(df[columns_to_scale])
nmf_scaled = pd.DataFrame(scaled_data, columns=columns_to_scale)
warnings.filterwarnings("ignore", category=UserWarning)
inertia = []
k = range(1, 11)
for i in k:
model = KMeans(n_clusters=i, n_init=10)
model.fit(nmf_scaled)
inertia.append(model.inertia_)
plt.plot(k, inertia, '-x')
plt.xlabel('Aantal (k) clusters')
plt.ylabel('inertia')
plt.xticks(k)
plt.show()
model = NMF(n_components=3, init='random', random_state=42)
nmf_features = model.fit_transform(scaled_data)
NMF = pd.DataFrame(nmf_features,
columns=[f'component{i+1}' for i in range(3)],
index=scaled_df.index)
NMF = NMF.apply(pd.to_numeric, errors='coerce')
NMF.dropna(inplace=True)
kmeans = KMeans(n_clusters=3, n_init=10, random_state=42)
NMF['cluster'] = kmeans.fit_predict(NMF)
print(NMF['cluster'].value_counts())
cluster 0 40 1 39 2 26 Name: count, dtype: int64
import plotly.express as px
fig = px.scatter_3d(NMF, x='component1', y='component2', z='component3', color='cluster',
symbol='cluster', opacity=0.7, size_max=10)
fig.update_layout(scene=dict(xaxis_title='Component 1', yaxis_title='Component 2', zaxis_title='Component 3'))
fig.show()
# Bron: (3D, z.d.)
Voor gegeven matrix V van dimensie m × n, m = het aantal rijen n = het aantal kolommen is, NMF maakt de matrices W en H k = het aantal componenten W = m × k H = k × n. De benadering WH wordt gebruikt om V te benaderen.
NMF maakt W en H door de volgende functie te minimaliseren $ ||V - WH||^2_F $ Hierbij is ∣∣⋅∣∣F de reconstructiefout, wat aangeeft hoe goed de benadering WH tot V is. Optimalisatie-algoritme: De optimalisatie van W en H wordt uitgevoerd met methoden als multiplicatieve update-regels. De meest voorkomende update-regels zijn:
Update W: $ W_{ij} = W_{ij} \frac{(VH^T)_{ij}}{(WHH^T)_{ij}} $
Update H: $ H_{ij} = H_{ij} \frac{(W^TV)_{ij}}{(W^TWH)_{ij}} $
Hierbij zijn WT en HT de nieuwe matrices van W en H. De updates worden toegepast totdat de reconstructiefout convergeert. W als H bestaat uit niet-negatieve elementen. de componenten die door NMF worden gemaakt zijn interpreteer baar en lijken op de originele patronen
Hypothetische dataset schoolcijfers:
Matrix V heeft cijfers van 4 studenten met 5 vakken (4x5):
$ V = \begin{bmatrix} 7 & 6 & 8 & 9 & 5 \\ 6 & 7 & 8 & 9 & 4 \\ 8 & 7 & 9 & 9 & 6 \\ 9 & 8 & 9 & 8 & 7 \\ \end{bmatrix} $
We willen de vaardigheid van studenten en de moeilijkheid van het vak als componenten nemen, ( K = 2 ).
Willekeurige initialisatie:
$ W = \begin{bmatrix} 1 & 2 \\ 3 & 4 \\ 5 & 6 \\ 7 & 8 \\ \end{bmatrix} $
$ H = \begin{bmatrix} 1 & 2 & 3 & 4 & 5 \\ 6 & 7 & 8 & 9 & 10 \\ \end{bmatrix} $
Na het toepassen van de update-regels voor optimalisatie, convergeren ( W ) en ( H ) naar:
$ W = \begin{bmatrix} 0.9 & 0.8 \\ 0.7 & 0.6 \\ 1.2 & 1.3 \\ 0.8 & 0.7 \\ \end{bmatrix} $
$ H = \begin{bmatrix} 4.6 & 5.7 & 6.5 & 7.2 & 4.8 \\ 1.5 & 1.7 & 1.8 & 1.9 & 1.3 \\ \end{bmatrix} $
Nu kan ( V ) worden benaderd, de reconstructie van ( V ) is:
$ \begin{bmatrix} 6.26 & 6.47 & 7.01 & 7.64 & 5.1 \\ 6.08 & 6.33 & 6.84 & 7.45 & 4.95 \\ 7.41 & 7.65 & 8.28 & 9.02 & 6.02 \\ 8.4 & 8.68 & 9.36 & 10.18& 6.8 \\ \end{bmatrix} $
Nu zijn de componenten interpreteerbaar sinds er maar 2 zijn en we precies weten wat ze betekenen.
3D. (z.d.). https://plotly.com/python/3d-scatter-plots/
Deruty, E. (2022, 15 december). Intuitive understanding of MFCCs - Emmanuel Deruty - Medium. Medium. https://medium.com/@derutycsl/intuitive-understanding-of-mfccs-836d36a1f779
Hathaway, R. B. (2005). TRANSDUCERS AND DATA ACQUISITION. In Elsevier eBooks (pp. 1–56). https://doi.org/10.1016/b978-075067719-6/50002-6
librosa.feature.spectral_contrast — librosa 0.10.1 documentation. (z.d.). https://librosa.org/doc/main/generated/librosa.feature.spectral_contrast.html
librosa.feature.tonnetz — librosa 0.10.1 documentation. (z.d.). https://librosa.org/doc/main/generated/librosa.feature.tonnetz.html
librosa.feature.spectral_rolloff — librosa 0.10.1 documentation. (z.d.). https://librosa.org/doc/main/generated/librosa.feature.spectral_rolloff.html
Wikipedia contributors. (2024b, februari 9). Chroma feature. Wikipedia. https://en.wikipedia.org/wiki/Chroma_feature
Verma, Y. (2021, 11 november). A Tutorial on Spectral Feature Extraction for Audio Analytics. Analytics India Magazine. https://analyticsindiamag.com/a-tutorial-on-spectral-feature-extraction-for-audio-analytics/
Wikipedia contributors. (2023, 1 december). Spectral flatness. Wikipedia. https://en.wikipedia.org/wiki/Spectral_flatness
Torres-García, A. A., Mendoza-Montoya, O., Molinas, M., Antelis, J. M., Moctezuma, L. A., & Hernández-Del-Toro, T. (2022). Pre-processing and feature extraction. In Elsevier eBooks (pp. 59–91). https://doi.org/10.1016/b978-0-12-820125-1.00014-2
Wikipedia contributors. (2024a, januari 5). Centroid. Wikipedia. https://en.wikipedia.org/wiki/Centroid
Wikipedia-bijdragers. (2023, 31 juli). Hoofdcomponentenanalyse. Wikipedia. Geraadpleegd op 21-1-2024 van https://nl.wikipedia.org/wiki/Hoofdcomponentenanalyse
Jaadi, Z. (2023, 29 maart). A Step-by-Step Explanation of Principal Component Analysis (PCA). Built In. Geraadpleegd op 21-1-2024 van https://builtin.com/data-science/step-step-explanation-principal-component-analysis
Beat and Tempo — Librosa 0.10.1 Documentation. (z.d.). https://librosa.org/doc/latest/beat.html
Filters — Librosa 0.10.1 documentation. (z.d.). https://librosa.org/doc/latest/filters.html#filter-bank-construction
Librosa.feature.spectral_centroid — Librosa 0.10.1 documentation. (z.d.). https://librosa.org/doc/latest/generated/librosa.feature.spectral_centroid.html
Librosa.feature.spectral_bandwidth — Librosa 0.10.1 Documentation. (z.d.). https://librosa.org/doc/latest/generated/librosa.feature.spectral_bandwidth.html
Librosa.feature.spectral_flatness — Librosa 0.10.1 Documentation. (z.d.). https://librosa.org/doc/latest/generated/librosa.feature.spectral_flatness.html
Librosa.feature.zero_crossing_rate — Librosa 0.10.1 Documentation. (z.d.). https://librosa.org/doc/latest/generated/librosa.feature.zero_crossing_rate.html
Librosa.feature.Tempogram — Librosa 0.10.1 documentation. (z.d.). https://librosa.org/doc/latest/generated/librosa.feature.tempogram.html
Scipy.spatial.distance.cityblock — SciPY v1.12.0 Manual. (z.d.). https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.cityblock.html
Scipy.spatial.distance.euclidean — SciPY v1.12.0 manual. (z.d.). https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.euclidean.html